From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- js/src/tests/non262/Array/11.1.4.js | 68 + js/src/tests/non262/Array/15.4.4.5-1.js | 187 + js/src/tests/non262/Array/15.4.4.5-2.js | 189 + js/src/tests/non262/Array/15.4.4.5-3.js | 145 + js/src/tests/non262/Array/array-001.js | 85 + .../non262/Array/array-length-set-during-for-in.js | 10 + .../non262/Array/array-length-set-on-nonarray.js | 26 + js/src/tests/non262/Array/at.js | 39 + js/src/tests/non262/Array/browser.js | 0 ...hange-array-by-copy-cross-compartment-create.js | 26 + ...ange-array-by-copy-errors-from-correct-realm.js | 77 + js/src/tests/non262/Array/concat-proxy.js | 25 + .../tests/non262/Array/concat-spreadable-basic.js | 37 + .../non262/Array/concat-spreadable-primitive.js | 34 + js/src/tests/non262/Array/fill.js | 97 + js/src/tests/non262/Array/filter.js | 53 + .../tests/non262/Array/findLast_findLastIndex.js | 285 + js/src/tests/non262/Array/find_findindex.js | 285 + js/src/tests/non262/Array/for_of_1.js | 138 + js/src/tests/non262/Array/for_of_2.js | 58 + js/src/tests/non262/Array/for_of_3.js | 60 + js/src/tests/non262/Array/for_of_4.js | 64 + js/src/tests/non262/Array/from-iterator-close.js | 183 + js/src/tests/non262/Array/from_async.js | 302 + js/src/tests/non262/Array/from_basics.js | 51 + js/src/tests/non262/Array/from_constructor.js | 56 + js/src/tests/non262/Array/from_errors.js | 152 + js/src/tests/non262/Array/from_iterable.js | 50 + js/src/tests/non262/Array/from_length_setter.js | 13 + js/src/tests/non262/Array/from_mapping.js | 41 + js/src/tests/non262/Array/from_primitive.js | 21 + js/src/tests/non262/Array/from_proxy.js | 55 + js/src/tests/non262/Array/from_realms.js | 37 + js/src/tests/non262/Array/from_string.js | 23 + js/src/tests/non262/Array/from_surfaces.js | 13 + js/src/tests/non262/Array/from_this.js | 48 + js/src/tests/non262/Array/frozen-dense-array.js | 42 + .../tests/non262/Array/frozen-dict-mode-length.js | 18 + js/src/tests/non262/Array/getter-name.js | 9 + .../non262/Array/group-callback-evaluation.js | 18 + .../non262/Array/group-propertkey-is-length.js | 15 + js/src/tests/non262/Array/group.js | 88 + .../tests/non262/Array/includes-trailing-holes.js | 16 + js/src/tests/non262/Array/includes.js | 59 + .../non262/Array/index-with-null-character.js | 18 + .../Array/indexOf-never-returns-negative-zero.js | 4 + js/src/tests/non262/Array/indexOf-packed-array.js | 40 + js/src/tests/non262/Array/isArray.js | 67 + js/src/tests/non262/Array/iterator_edge_cases.js | 50 + js/src/tests/non262/Array/join-01.js | 83 + js/src/tests/non262/Array/join-no-has-trap.js | 36 + .../lastIndexOf-never-returns-negative-zero.js | 4 + js/src/tests/non262/Array/length-01.js | 71 + .../Array/length-nonwritable-redefine-nop.js | 70 + js/src/tests/non262/Array/length-set-object.js | 68 + .../length-truncate-nonconfigurable-sparse.js | 110 + .../Array/length-truncate-nonconfigurable.js | 48 + .../non262/Array/length-truncate-with-indexed.js | 101 + js/src/tests/non262/Array/pop-empty-nonwritable.js | 32 + js/src/tests/non262/Array/pop-no-has-trap.js | 58 + .../non262/Array/pop-nonarray-higher-elements.js | 91 + .../tests/non262/Array/redefine-length-accessor.js | 42 + .../non262/Array/redefine-length-frozen-array.js | 26 + .../redefine-length-frozen-dictionarymode-array.js | 36 + ...ritable-length-custom-conversion-call-counts.js | 45 + ...e-nonwritable-length-custom-conversion-throw.js | 58 + .../redefine-nonwritable-length-nonnumeric.js | 32 + js/src/tests/non262/Array/regress-101488.js | 135 + js/src/tests/non262/Array/regress-107138.js | 174 + js/src/tests/non262/Array/regress-108440.js | 77 + js/src/tests/non262/Array/regress-130451.js | 182 + js/src/tests/non262/Array/regress-154338.js | 87 + js/src/tests/non262/Array/regress-157652.js | 117 + js/src/tests/non262/Array/regress-178722.js | 127 + js/src/tests/non262/Array/regress-255555.js | 32 + js/src/tests/non262/Array/regress-290592.js | 661 + js/src/tests/non262/Array/regress-299644.js | 27 + js/src/tests/non262/Array/regress-300858.js | 21 + js/src/tests/non262/Array/regress-304828.js | 256 + js/src/tests/non262/Array/regress-305002.js | 25 + js/src/tests/non262/Array/regress-310351.js | 54 + js/src/tests/non262/Array/regress-310425-01.js | 27 + js/src/tests/non262/Array/regress-310425-02.js | 17 + js/src/tests/non262/Array/regress-311515.js | 20 + js/src/tests/non262/Array/regress-315509-01.js | 28 + js/src/tests/non262/Array/regress-322135-01.js | 39 + js/src/tests/non262/Array/regress-330812.js | 33 + js/src/tests/non262/Array/regress-345961.js | 33 + js/src/tests/non262/Array/regress-348810.js | 25 + js/src/tests/non262/Array/regress-350256-01.js | 42 + js/src/tests/non262/Array/regress-350256-02.js | 43 + js/src/tests/non262/Array/regress-352742-01.js | 36 + js/src/tests/non262/Array/regress-352742-02.js | 29 + js/src/tests/non262/Array/regress-360681-01.js | 30 + js/src/tests/non262/Array/regress-360681-02.js | 55 + js/src/tests/non262/Array/regress-364104.js | 74 + js/src/tests/non262/Array/regress-386030.js | 64 + js/src/tests/non262/Array/regress-387501.js | 48 + js/src/tests/non262/Array/regress-390598.js | 37 + js/src/tests/non262/Array/regress-415451.js | 24 + js/src/tests/non262/Array/regress-421325.js | 31 + js/src/tests/non262/Array/regress-422286.js | 31 + js/src/tests/non262/Array/regress-424954.js | 27 + js/src/tests/non262/Array/regress-430717.js | 29 + js/src/tests/non262/Array/regress-451483.js | 28 + js/src/tests/non262/Array/regress-451906.js | 27 + js/src/tests/non262/Array/regress-456845.js | 48 + js/src/tests/non262/Array/regress-465980-01.js | 32 + js/src/tests/non262/Array/regress-465980-02.js | 107 + js/src/tests/non262/Array/regress-474529.js | 52 + js/src/tests/non262/Array/regress-488989.js | 32 + js/src/tests/non262/Array/regress-566651.js | 20 + js/src/tests/non262/Array/regress-599159.js | 10 + js/src/tests/non262/Array/regress-619970.js | 8 + js/src/tests/non262/Array/regress-94257.js | 83 + .../Array/reverse-order-of-low-high-accesses.js | 88 + ...set-with-indexed-property-on-prototype-chain.js | 60 + js/src/tests/non262/Array/shell.js | 0 js/src/tests/non262/Array/shift-no-has-trap.js | 64 + js/src/tests/non262/Array/shift_for_in.js | 13 + .../non262/Array/slice-sparse-with-large-index.js | 18 + js/src/tests/non262/Array/sort-01.js | 23 + .../Array/sort-array-with-holes-and-undefined.js | 32 + .../non262/Array/sort-delete-ascending-order.js | 37 + js/src/tests/non262/Array/sort-non-function.js | 22 + .../Array/sort-typedarray-with-own-length.js | 33 + js/src/tests/non262/Array/sort_basics.js | 46 + js/src/tests/non262/Array/sort_holes.js | 66 + .../tests/non262/Array/sort_native_string_nan.js | 16 + js/src/tests/non262/Array/sort_proxy.js | 38 + js/src/tests/non262/Array/sort_small.js | 33 + js/src/tests/non262/Array/species.js | 182 + ...splice-return-array-elements-defined-not-set.js | 46 + .../non262/Array/splice-species-changes-length.js | 48 + .../Array/splice-suppresses-unvisited-indexes.js | 61 + js/src/tests/non262/Array/to-length.js | 40 + js/src/tests/non262/Array/toLocaleString-01.js | 36 + js/src/tests/non262/Array/toLocaleString-nointl.js | 26 + js/src/tests/non262/Array/toLocaleString.js | 14 + js/src/tests/non262/Array/toSpliced-dense.js | 127 + js/src/tests/non262/Array/toSpliced.js | 27 + js/src/tests/non262/Array/toString-01.js | 52 + js/src/tests/non262/Array/unscopables.js | 61 + js/src/tests/non262/Array/unshift-01.js | 44 + .../tests/non262/Array/unshift-with-enumeration.js | 18 + js/src/tests/non262/Array/values.js | 20 + js/src/tests/non262/Array/with-dense.js | 103 + js/src/tests/non262/Array/with.js | 17 + .../tests/non262/ArrayBuffer/CloneArrayBuffer.js | 35 + js/src/tests/non262/ArrayBuffer/browser.js | 0 js/src/tests/non262/ArrayBuffer/bug1689503.js | 9 + js/src/tests/non262/ArrayBuffer/bug1777413.js | 7 + .../non262/ArrayBuffer/constructorNotCallable.js | 8 + js/src/tests/non262/ArrayBuffer/getter-name.js | 10 + js/src/tests/non262/ArrayBuffer/shell.js | 0 js/src/tests/non262/ArrayBuffer/slice-species.js | 180 + .../async-generator-declaration-in-modules.js | 11 + js/src/tests/non262/AsyncGenerators/browser.js | 0 .../create-function-parse-before-getprototype.js | 19 + .../non262/AsyncGenerators/cross-compartment.js | 90 + .../non262/AsyncGenerators/for-await-bad-syntax.js | 24 + .../non262/AsyncGenerators/for-await-of-error.js | 26 + js/src/tests/non262/AsyncGenerators/shell.js | 0 js/src/tests/non262/AsyncIterator/asynciterator.js | 13 + .../AsyncIterator/constructor-subclassable.js | 12 + .../constructor-throw-when-called-directly.js | 9 + .../AsyncIterator/constructor-throw-without-new.js | 9 + js/src/tests/non262/AsyncIterator/constructor.js | 9 + js/src/tests/non262/AsyncIterator/length.js | 13 + js/src/tests/non262/AsyncIterator/name.js | 13 + js/src/tests/non262/AsyncIterator/proto.js | 14 + .../prototype/asIndexedPairs/asIndexedPairs.js | 25 + .../prototype/asIndexedPairs/length.js | 21 + .../AsyncIterator/prototype/asIndexedPairs/name.js | 20 + .../async-iterator-helpers-from-other-global.js | 65 + .../AsyncIterator/prototype/clobber-symbol.js | 50 + .../prototype/drop/drop-more-than-available.js | 39 + .../non262/AsyncIterator/prototype/drop/drop.js | 23 + .../non262/AsyncIterator/prototype/drop/length.js | 20 + .../non262/AsyncIterator/prototype/drop/name.js | 20 + .../AsyncIterator/prototype/every/async-writes.js | 20 + .../every/check-fn-after-getting-iterator.js | 30 + .../prototype/every/coerce-result-to-boolean.js | 29 + .../AsyncIterator/prototype/every/descriptor.js | 10 + .../prototype/every/error-from-correct-realm.js | 21 + .../prototype/every/fn-not-callable-throws.js | 26 + .../prototype/every/fn-throws-close-iterator.js | 24 + .../prototype/every/interleaving-calls.js | 24 + .../non262/AsyncIterator/prototype/every/length.js | 17 + .../non262/AsyncIterator/prototype/every/name.js | 13 + .../every/next-throws-iterator-not-closed.js | 24 + .../non262/AsyncIterator/prototype/every/proxy.js | 46 + .../prototype/every/return-true-if-all-match.js | 16 + .../prototype/every/short-circuit-on-false.js | 21 + .../prototype/every/this-not-iterator-throws.js | 22 + .../every/value-throws-iterator-not-closed.js | 28 + .../prototype/filter/coerce-result-to-boolean.js | 25 + .../AsyncIterator/prototype/filter/filter.js | 24 + .../AsyncIterator/prototype/filter/length.js | 21 + .../non262/AsyncIterator/prototype/filter/name.js | 19 + .../AsyncIterator/prototype/find/async-writes.js | 20 + .../find/check-fn-after-getting-iterator.js | 28 + .../prototype/find/coerce-result-to-boolean.js | 35 + .../AsyncIterator/prototype/find/descriptor.js | 13 + .../prototype/find/error-from-correct-realm.js | 21 + .../prototype/find/fn-not-callable-throws.js | 26 + .../prototype/find/fn-throws-close-iterator.js | 26 + .../prototype/find/interleaving-calls.js | 24 + .../non262/AsyncIterator/prototype/find/length.js | 17 + .../non262/AsyncIterator/prototype/find/name.js | 13 + .../find/next-throws-iterator-not-closed.js | 24 + .../non262/AsyncIterator/prototype/find/proxy.js | 46 + .../find/return-undefined-if-none-match.js | 16 + .../prototype/find/short-circuit-on-match.js | 21 + .../prototype/find/this-not-iterator-throws.js | 20 + .../find/value-throws-iterator-not-closed.js | 28 + .../close-iterator-when-inner-complete-throws.js | 55 + .../close-iterator-when-inner-next-throws.js | 50 + .../close-iterator-when-inner-value-throws.js | 57 + .../AsyncIterator/prototype/flatMap/flatMap.js | 28 + .../prototype/flatMap/inner-empty-iterable.js | 44 + .../prototype/flatMap/inner-generator.js | 36 + .../AsyncIterator/prototype/flatMap/length.js | 21 + .../non262/AsyncIterator/prototype/flatMap/name.js | 19 + .../flatMap/throw-when-inner-not-iterable.js | 71 + .../prototype/forEach/async-writes.js | 20 + .../forEach/check-fn-after-getting-iterator.js | 27 + .../AsyncIterator/prototype/forEach/descriptor.js | 13 + .../prototype/forEach/error-from-correct-realm.js | 21 + .../prototype/forEach/fn-not-callable-throws.js | 24 + .../prototype/forEach/fn-throws-close-iterator.js | 24 + .../AsyncIterator/prototype/forEach/forEach.js | 11 + .../prototype/forEach/interleaving-calls.js | 24 + .../AsyncIterator/prototype/forEach/length.js | 17 + .../non262/AsyncIterator/prototype/forEach/name.js | 13 + .../forEach/next-throws-iterator-not-closed.js | 24 + .../AsyncIterator/prototype/forEach/proxy.js | 44 + .../prototype/forEach/this-not-iterator-throws.js | 19 + .../forEach/value-throws-iterator-not-closed.js | 28 + .../generator-methods-throw-on-iterator-helpers.js | 35 + .../iterator-helper-methods-throw-on-generators.js | 12 + .../prototype/lazy-methods-from-other-global.js | 36 + .../lazy-methods-handle-empty-iterators.js | 42 + .../prototype/lazy-methods-interleaved.js | 59 + .../lazy-methods-iterator-closed-on-call-throws.js | 49 + ...lazy-methods-iterator-closed-on-yield-throws.js | 53 + ...-iterator-not-closed-on-next-get-then-throws.js | 57 + ...r-not-closed-on-next-promise-executor-throws.js | 53 + ...s-iterator-not-closed-on-next-returns-reject.js | 51 + ...hods-iterator-not-closed-on-next-then-throws.js | 57 + ...y-methods-iterator-not-closed-on-next-throws.js | 49 + ...-methods-iterator-not-closed-on-value-throws.js | 54 + ...ods-iterator-returns-done-generator-finishes.js | 30 + ...-methods-multiple-return-close-iterator-once.js | 64 + ...y-methods-multiple-throw-close-iterator-once.js | 90 + .../lazy-methods-mutate-iterator-after-done.js | 49 + .../prototype/lazy-methods-mutate-iterator.js | 49 + .../lazy-methods-not-close-iterator-next-reject.js | 48 + .../lazy-methods-pass-through-lastValue.js | 33 + .../lazy-methods-pass-value-through-chain.js | 38 + .../prototype/lazy-methods-proxy-accesses.js | 68 + .../lazy-methods-return-closes-iterator.js | 63 + .../lazy-methods-return-new-iterator-result.js | 42 + ...zy-methods-throw-closes-iterator-before-next.js | 58 + ...y-methods-throw-eagerly-on-next-non-callable.js | 35 + .../lazy-methods-throw-eagerly-on-non-callable.js | 40 + .../lazy-methods-throw-eagerly-on-non-iterator.js | 31 + .../lazy-methods-throw-next-done-throws.js | 53 + .../lazy-methods-throw-next-not-object.js | 50 + .../prototype/lazy-methods-throw-on-reentry.js | 18 + .../non262/AsyncIterator/prototype/map/length.js | 21 + .../non262/AsyncIterator/prototype/map/map.js | 23 + .../non262/AsyncIterator/prototype/map/name.js | 19 + .../reduce/accumulator-set-to-initial-value.js | 13 + .../AsyncIterator/prototype/reduce/async-writes.js | 20 + .../reduce/check-fn-after-getting-iterator.js | 27 + .../AsyncIterator/prototype/reduce/descriptor.js | 13 + .../empty-iterator-without-initial-value-throws.js | 9 + .../prototype/reduce/error-from-correct-realm.js | 21 + .../prototype/reduce/interleaving-calls.js | 24 + .../reduce/iterator-empty-return-initial-value.js | 9 + .../iterator-next-return-non-object-throws.js | 31 + .../prototype/reduce/left-associative.js | 15 + .../AsyncIterator/prototype/reduce/length.js | 17 + .../non262/AsyncIterator/prototype/reduce/name.js | 13 + .../reduce/next-throws-iterator-not-closed.js | 24 + ...initial-value-set-accumulator-to-first-value.js | 13 + .../non262/AsyncIterator/prototype/reduce/proxy.js | 44 + .../AsyncIterator/prototype/reduce/reduce.js | 13 + .../reduce/reducer-not-callable-throws.js | 24 + .../reduce/reducer-throws-iterator-closed.js | 24 + .../prototype/reduce/this-not-iterator-throws.js | 19 + .../reduce/value-throws-iterator-not-closed.js | 28 + .../AsyncIterator/prototype/some/async-writes.js | 20 + .../some/check-fn-after-getting-iterator.js | 31 + .../prototype/some/coerce-result-to-boolean.js | 29 + .../AsyncIterator/prototype/some/descriptor.js | 13 + .../prototype/some/error-from-correct-realm.js | 21 + .../prototype/some/fn-not-callable-throws.js | 28 + .../prototype/some/fn-throws-close-iterator.js | 24 + .../prototype/some/interleaving-calls.js | 24 + .../non262/AsyncIterator/prototype/some/length.js | 17 + .../non262/AsyncIterator/prototype/some/name.js | 13 + .../some/next-throws-iterator-not-closed.js | 23 + .../non262/AsyncIterator/prototype/some/proxy.js | 46 + .../prototype/some/return-false-if-none-match.js | 16 + .../prototype/some/short-circuit-on-true.js | 20 + .../prototype/some/this-not-iterator-throws.js | 19 + .../some/value-throws-iterator-not-closed.js | 28 + .../take-drop-throw-eagerly-on-negative.js | 30 + .../take-drop-throw-eagerly-on-non-integer.js | 33 + .../take/close-iterator-when-none-remaining.js | 45 + .../non262/AsyncIterator/prototype/take/length.js | 21 + .../non262/AsyncIterator/prototype/take/name.js | 19 + .../prototype/take/take-more-than-available.js | 34 + .../non262/AsyncIterator/prototype/take/take.js | 23 + .../prototype/toArray/async-writes.js | 20 + .../prototype/toArray/create-in-current-realm.js | 22 + .../AsyncIterator/prototype/toArray/descriptor.js | 13 + .../prototype/toArray/interleaving-calls.js | 24 + .../prototype/toArray/iterator-empty.js | 10 + .../AsyncIterator/prototype/toArray/length.js | 17 + .../non262/AsyncIterator/prototype/toArray/name.js | 13 + .../AsyncIterator/prototype/toArray/next-throws.js | 23 + .../AsyncIterator/prototype/toArray/proxy.js | 44 + .../prototype/toArray/this-not-iterator-throws.js | 21 + .../AsyncIterator/prototype/toArray/toArray.js | 22 + .../toArray/value-throws-iterator-not-closed.js | 33 + js/src/tests/non262/Atomics/browser.js | 0 js/src/tests/non262/Atomics/cross-compartment.js | 109 + js/src/tests/non262/Atomics/detached-buffers.js | 94 + js/src/tests/non262/Atomics/shell.js | 0 .../non262/BigInt/Number-conversion-rounding.js | 244 + js/src/tests/non262/BigInt/decimal.js | 30 + js/src/tests/non262/BigInt/large-bit-length.js | 33 + js/src/tests/non262/BigInt/mod.js | 8 + .../non262/BigInt/property-name-guessed-name.js | 21 + js/src/tests/non262/BigInt/property-name.js | 194 + js/src/tests/non262/Boolean/15.6.4.2.js | 17 + js/src/tests/non262/Boolean/browser.js | 0 js/src/tests/non262/Boolean/no-boolean-toJSON.js | 17 + js/src/tests/non262/Boolean/shell.js | 0 js/src/tests/non262/DataView/browser.js | 0 .../non262/DataView/detach-after-construction.js | 9 + .../tests/non262/DataView/get-set-index-range.js | 36 + js/src/tests/non262/DataView/getter-name.js | 11 + js/src/tests/non262/DataView/shell.js | 0 js/src/tests/non262/Date/15.9.4.2.js | 134 + js/src/tests/non262/Date/15.9.5.5-02.js | 63 + js/src/tests/non262/Date/15.9.5.5.js | 111 + js/src/tests/non262/Date/15.9.5.6.js | 118 + js/src/tests/non262/Date/15.9.5.7.js | 110 + .../tests/non262/Date/UTC-convert-all-arguments.js | 70 + js/src/tests/non262/Date/browser.js | 12 + .../Date/constructor-convert-all-arguments.js | 70 + .../non262/Date/constructor-one-Date-argument.js | 40 + .../tests/non262/Date/constructor-one-argument.js | 26 + js/src/tests/non262/Date/dashed-date.js | 155 + js/src/tests/non262/Date/defaultvalue.js | 190 + .../tests/non262/Date/dst-offset-caching-1-of-8.js | 6 + .../tests/non262/Date/dst-offset-caching-2-of-8.js | 6 + .../tests/non262/Date/dst-offset-caching-3-of-8.js | 6 + .../tests/non262/Date/dst-offset-caching-4-of-8.js | 6 + .../tests/non262/Date/dst-offset-caching-5-of-8.js | 6 + .../tests/non262/Date/dst-offset-caching-6-of-8.js | 6 + .../tests/non262/Date/dst-offset-caching-7-of-8.js | 6 + .../tests/non262/Date/dst-offset-caching-8-of-8.js | 6 + js/src/tests/non262/Date/equality-to-boolean.js | 39 + js/src/tests/non262/Date/fractions.js | 24 + js/src/tests/non262/Date/non-iso.js | 71 + .../tests/non262/Date/parse-dashed-numeric-date.js | 133 + js/src/tests/non262/Date/parse-day-of-week.js | 93 + .../non262/Date/parse-from-tostring-methods.js | 31 + js/src/tests/non262/Date/parse-keywords.js | 50 + js/src/tests/non262/Date/parse-milliseconds.js | 66 + js/src/tests/non262/Date/parse-month.js | 91 + .../tests/non262/Date/parse-num-preceding-alpha.js | 44 + js/src/tests/non262/Date/parse-period.js | 46 + js/src/tests/non262/Date/parse-single-number.js | 60 + js/src/tests/non262/Date/parse-time-zone.js | 10 + .../non262/Date/parse-timezone-without-gmt.js | 118 + .../tests/non262/Date/parse-year-after-timezone.js | 42 + js/src/tests/non262/Date/parse-zulu-time.js | 21 + .../tests/non262/Date/prototype-is-not-a-date.js | 15 + js/src/tests/non262/Date/regress-188211.js | 27 + js/src/tests/non262/Date/regress-301738-01.js | 97 + js/src/tests/non262/Date/regress-309925-01.js | 15 + js/src/tests/non262/Date/regress-309925-02.js | 15 + js/src/tests/non262/Date/regress-346027.js | 27 + js/src/tests/non262/Date/regress-346363.js | 28 + js/src/tests/non262/Date/regress-452786.js | 30 + .../Date/reset-time-zone-cache-same-offset.js | 30 + .../Date/setTime-argument-shortcircuiting.js | 147 + js/src/tests/non262/Date/shell.js | 311 + .../non262/Date/time-components-negative-zero.js | 18 + js/src/tests/non262/Date/time-zone-2038-pst.js | 43 + .../tests/non262/Date/time-zone-etc_localetime.js | 29 + js/src/tests/non262/Date/time-zone-path.js | 56 + js/src/tests/non262/Date/time-zone-pst.js | 120 + js/src/tests/non262/Date/time-zones-historic.js | 538 + js/src/tests/non262/Date/time-zones-imported.js | 1020 + js/src/tests/non262/Date/time-zones-pedantic.js | 15 + js/src/tests/non262/Date/time-zones-posix.js | 160 + js/src/tests/non262/Date/time-zones.js | 261 + js/src/tests/non262/Date/timeclip.js | 42 + js/src/tests/non262/Date/to-temporal-instant.js | 62 + js/src/tests/non262/Date/toISOString-01.js | 53 + js/src/tests/non262/Date/toISOString.js | 24 + js/src/tests/non262/Date/toJSON-01.js | 238 + js/src/tests/non262/Date/toPrimitive.js | 62 + js/src/tests/non262/Date/toString-generic.js | 15 + .../tests/non262/Date/toString-localized-posix.js | 71 + js/src/tests/non262/Date/toString-localized.js | 90 + js/src/tests/non262/Date/two-digit-years.js | 71 + js/src/tests/non262/Error/AggregateError.js | 80 + js/src/tests/non262/Error/browser.js | 0 js/src/tests/non262/Error/constructor-ordering.js | 17 + js/src/tests/non262/Error/constructor-proto.js | 17 + js/src/tests/non262/Error/prototype-properties.js | 26 + js/src/tests/non262/Error/prototype.js | 18 + js/src/tests/non262/Error/regress-354246.js | 34 + js/src/tests/non262/Error/regress-412324.js | 17 + js/src/tests/non262/Error/regress-465377.js | 78 + js/src/tests/non262/Error/shell.js | 0 js/src/tests/non262/Exceptions/browser.js | 0 js/src/tests/non262/Exceptions/catchguard-002-n.js | 31 + js/src/tests/non262/Exceptions/catchguard-003-n.js | 35 + .../non262/Exceptions/error-expando-reconfigure.js | 28 + .../Exceptions/error-property-enumerability.js | 30 + js/src/tests/non262/Exceptions/errstack-001.js | 242 + js/src/tests/non262/Exceptions/regress-121658.js | 121 + js/src/tests/non262/Exceptions/regress-123002.js | 90 + js/src/tests/non262/Exceptions/regress-181654.js | 118 + js/src/tests/non262/Exceptions/regress-181914.js | 157 + js/src/tests/non262/Exceptions/regress-257751.js | 92 + js/src/tests/non262/Exceptions/regress-273931.js | 74 + js/src/tests/non262/Exceptions/regress-332472.js | 25 + js/src/tests/non262/Exceptions/regress-333728.js | 83 + js/src/tests/non262/Exceptions/regress-342359.js | 43 + js/src/tests/non262/Exceptions/regress-347674.js | 63 + js/src/tests/non262/Exceptions/regress-350650-n.js | 28 + js/src/tests/non262/Exceptions/regress-350837.js | 43 + js/src/tests/non262/Exceptions/regress-58946.js | 33 + js/src/tests/non262/Exceptions/regress-95101.js | 81 + js/src/tests/non262/Exceptions/shell.js | 0 js/src/tests/non262/Function/10.1.6-01.js | 29 + js/src/tests/non262/Function/10.1.6.js | 23 + js/src/tests/non262/Function/10.2.1.1.6.js | 35 + js/src/tests/non262/Function/15.3.4.3-01.js | 245 + .../tests/non262/Function/Function-arguments-gc.js | 40 + js/src/tests/non262/Function/Function-prototype.js | 11 + js/src/tests/non262/Function/Function-with-eval.js | 25 + js/src/tests/non262/Function/Object-toSource.js | 373 + .../non262/Function/arguments-caller-callee.js | 64 + .../non262/Function/arguments-extra-property.js | 33 + js/src/tests/non262/Function/arguments-iterator.js | 167 + .../Function/arguments-parameter-shadowing.js | 22 + .../Function/arguments-property-attributes.js | 98 + .../tests/non262/Function/arrow-has-duplicated.js | 15 + .../tests/non262/Function/bound-length-and-name.js | 40 + .../non262/Function/bound-non-constructable.js | 17 + js/src/tests/non262/Function/bound-prototype.js | 37 + js/src/tests/non262/Function/browser.js | 0 .../tests/non262/Function/builtin-no-construct.js | 52 + .../tests/non262/Function/builtin-no-prototype.js | 40 + .../Function/configurable-length-builtins.js | 21 + .../tests/non262/Function/configurable-length.js | 86 + .../construct-bound-proxy-with-many-arguments.js | 13 + .../tests/non262/Function/constructor-binding.js | 11 + .../create-function-parse-before-getprototype.js | 17 + js/src/tests/non262/Function/function-bind.js | 280 + js/src/tests/non262/Function/function-call.js | 134 + .../Function/function-caller-restrictions.js | 29 + js/src/tests/non262/Function/function-caller.js | 45 + ...tor-toString-arguments-before-parsing-params.js | 23 + .../non262/Function/function-name-assignment.js | 139 + .../tests/non262/Function/function-name-binding.js | 54 + .../tests/non262/Function/function-name-class.js | 32 + .../non262/Function/function-name-computed-01.js | 57 + .../non262/Function/function-name-computed-02.js | 57 + js/src/tests/non262/Function/function-name-for.js | 31 + .../tests/non262/Function/function-name-method.js | 70 + .../non262/Function/function-name-property.js | 58 + js/src/tests/non262/Function/function-name.js | 64 + .../Function/function-toString-builtin-name.js | 53 + .../non262/Function/function-toString-builtin.js | 42 + js/src/tests/non262/Function/get-function-realm.js | 45 + .../tests/non262/Function/has-instance-jitted.js | 96 + js/src/tests/non262/Function/has-instance.js | 101 + .../implicit-this-in-parameter-expression.js | 18 + .../non262/Function/invalid-parameter-list.js | 27 + ...-with-destructuring-and-parameter-expression.js | 31 + .../Function/line-terminator-before-arrow.js | 9 + .../tests/non262/Function/method-has-duplicated.js | 19 + .../non262/Function/parameter-redeclaration.js | 19 + .../non262/Function/redefine-arguments-length.js | 65 + js/src/tests/non262/Function/regress-123371.js | 19 + js/src/tests/non262/Function/regress-131964.js | 159 + js/src/tests/non262/Function/regress-137181.js | 76 + js/src/tests/non262/Function/regress-178389.js | 26 + js/src/tests/non262/Function/regress-193555.js | 99 + js/src/tests/non262/Function/regress-222029-001.js | 123 + js/src/tests/non262/Function/regress-222029-002.js | 132 + js/src/tests/non262/Function/regress-292215.js | 37 + js/src/tests/non262/Function/regress-313570.js | 30 + js/src/tests/non262/Function/regress-338121-01.js | 37 + js/src/tests/non262/Function/regress-338121-02.js | 36 + js/src/tests/non262/Function/regress-344052.js | 27 + js/src/tests/non262/Function/regress-364023.js | 37 + js/src/tests/non262/Function/regress-49286.js | 100 + js/src/tests/non262/Function/regress-518103.js | 27 + js/src/tests/non262/Function/regress-524826.js | 28 + js/src/tests/non262/Function/regress-528082.js | 20 + js/src/tests/non262/Function/regress-533254.js | 28 + js/src/tests/non262/Function/regress-545980.js | 41 + js/src/tests/non262/Function/regress-58274.js | 189 + js/src/tests/non262/Function/regress-85880.js | 136 + js/src/tests/non262/Function/regress-94506.js | 126 + js/src/tests/non262/Function/regress-97921.js | 115 + .../tests/non262/Function/rest-has-duplicated.js | 17 + .../tests/non262/Function/rest-parameter-names.js | 68 + js/src/tests/non262/Function/return-finally.js | 172 + js/src/tests/non262/Function/shell.js | 0 .../non262/Function/spread-iterator-primitive.js | 28 + js/src/tests/non262/Function/strict-arguments.js | 453 + js/src/tests/non262/Function/throw-type-error.js | 16 + js/src/tests/non262/GC/browser.js | 0 js/src/tests/non262/GC/regress-104584.js | 46 + js/src/tests/non262/GC/regress-203278-2.js | 80 + js/src/tests/non262/GC/regress-203278-3.js | 42 + js/src/tests/non262/GC/regress-278725.js | 29 + js/src/tests/non262/GC/regress-306788.js | 24 + js/src/tests/non262/GC/regress-311497.js | 61 + js/src/tests/non262/GC/regress-313276.js | 40 + js/src/tests/non262/GC/regress-313479.js | 37 + js/src/tests/non262/GC/regress-316885-01.js | 33 + js/src/tests/non262/GC/regress-316885-02.js | 42 + js/src/tests/non262/GC/regress-316885-03.js | 42 + js/src/tests/non262/GC/regress-319980-01.js | 117 + js/src/tests/non262/GC/regress-324278.js | 63 + js/src/tests/non262/GC/regress-331719.js | 19 + js/src/tests/non262/GC/regress-338653.js | 41 + js/src/tests/non262/GC/regress-341877-01.js | 40 + js/src/tests/non262/GC/regress-341877-02.js | 45 + js/src/tests/non262/GC/regress-348532.js | 51 + js/src/tests/non262/GC/regress-352606.js | 25 + js/src/tests/non262/GC/regress-383269-01.js | 59 + js/src/tests/non262/GC/regress-383269-02.js | 63 + js/src/tests/non262/GC/regress-390078.js | 33 + js/src/tests/non262/GC/regress-418128.js | 36 + js/src/tests/non262/GC/regress-440558.js | 34 + js/src/tests/non262/GC/shell.js | 0 js/src/tests/non262/Intl/Array/shell.js | 0 .../tests/non262/Intl/Array/toLocaleString-date.js | 53 + .../non262/Intl/Array/toLocaleString-number.js | 34 + js/src/tests/non262/Intl/Array/toLocaleString.js | 35 + .../non262/Intl/Collator/big5han-gb2312han.js | 22 + js/src/tests/non262/Intl/Collator/browser.js | 0 js/src/tests/non262/Intl/Collator/call.js | 74 + js/src/tests/non262/Intl/Collator/caseFirst.js | 197 + js/src/tests/non262/Intl/Collator/collation.js | 90 + js/src/tests/non262/Intl/Collator/compare.js | 137 + .../non262/Intl/Collator/construct-newtarget.js | 81 + .../non262/Intl/Collator/cross-compartment.js | 22 + .../non262/Intl/Collator/ignorePunctuation.js | 60 + js/src/tests/non262/Intl/Collator/implicithan.js | 17 + js/src/tests/non262/Intl/Collator/shell.js | 0 .../non262/Intl/Collator/supportedLocalesOf.js | 355 + js/src/tests/non262/Intl/Collator/toStringTag.js | 29 + js/src/tests/non262/Intl/Date/browser.js | 0 js/src/tests/non262/Intl/Date/shell.js | 0 .../Intl/Date/toLocaleDateString_timeZone.js | 77 + .../non262/Intl/Date/toLocaleString_timeZone.js | 77 + .../Intl/Date/toLocaleTimeString_timeZone.js | 77 + js/src/tests/non262/Intl/DateTimeFormat/browser.js | 3 + .../non262/Intl/DateTimeFormat/calendar-aliases.js | 35 + .../non262/Intl/DateTimeFormat/calendar-option.js | 67 + js/src/tests/non262/Intl/DateTimeFormat/call.js | 184 + .../Intl/DateTimeFormat/construct-newtarget.js | 81 + .../Intl/DateTimeFormat/cross-compartment.js | 70 + .../non262/Intl/DateTimeFormat/dateTimeStyle.js | 57 + .../Intl/DateTimeFormat/day-period-hour-cycle.js | 102 + .../Intl/DateTimeFormat/day-period-standalone.js | 160 + .../tests/non262/Intl/DateTimeFormat/day-period.js | 40 + js/src/tests/non262/Intl/DateTimeFormat/era.js | 245 + .../DateTimeFormat/extended-time-zone-names.js | 124 + .../non262/Intl/DateTimeFormat/field-widths.js | 225 + .../Intl/DateTimeFormat/format-timeZone-offset.js | 109 + js/src/tests/non262/Intl/DateTimeFormat/format.js | 47 + .../formatRange-gregorian-proleptic.js | 28 + .../Intl/DateTimeFormat/formatRange-hour-cycle.js | 450 + .../formatRange-matches-format-output.js | 58 + .../formatRange-original-skeleton.js | 18 + .../DateTimeFormat/formatRange-timeZone-offset.js | 77 + .../formatRange-timeZoneName-matches-format.js | 45 + .../DateTimeFormat/formatRange-timeZoneName.js | 124 + .../non262/Intl/DateTimeFormat/formatToParts.js | 96 + .../DateTimeFormat/format_timeZone-non-meta.js | 62 + .../non262/Intl/DateTimeFormat/format_timeZone.js | 104 + .../fractional-second-digits-append-item.js | 58 + .../DateTimeFormat/fractional-second-digits.js | 43 + .../tests/non262/Intl/DateTimeFormat/hourCycle.js | 142 + .../implied-script-has-consistent-output.js | 59 + js/src/tests/non262/Intl/DateTimeFormat/islamic.js | 89 + .../Intl/DateTimeFormat/japanese-gannen-year.js | 54 + .../non262/Intl/DateTimeFormat/mozExtensions.js | 18 + .../Intl/DateTimeFormat/numberingSystem-option.js | 60 + .../DateTimeFormat/options-property-accesses.js | 53 + .../non262/Intl/DateTimeFormat/related-year.js | 185 + js/src/tests/non262/Intl/DateTimeFormat/shell.js | 136 + .../non262/Intl/DateTimeFormat/standalone-month.js | 11 + .../Intl/DateTimeFormat/supportedLocalesOf.js | 371 + .../tests/non262/Intl/DateTimeFormat/timeZone.js | 139 + .../Intl/DateTimeFormat/timeZone_backward_links.js | 156 + .../Intl/DateTimeFormat/timeZone_backzone.js | 152 + .../Intl/DateTimeFormat/timeZone_backzone_links.js | 48 + .../DateTimeFormat/timeZone_notbackward_links.js | 31 + .../non262/Intl/DateTimeFormat/timeZone_version.js | 17 + .../non262/Intl/DateTimeFormat/toStringTag.js | 29 + .../Intl/DateTimeFormat/tz-environment-variable.js | 67 + .../tests/non262/Intl/DateTimeFormat/unwrapping.js | 248 + .../tests/non262/Intl/DisplayNames/abbreviated.js | 28 + .../Intl/DisplayNames/alias-and-parent-locales.js | 33 + js/src/tests/non262/Intl/DisplayNames/browser.js | 0 js/src/tests/non262/Intl/DisplayNames/calendar.js | 123 + js/src/tests/non262/Intl/DisplayNames/currency.js | 150 + .../non262/Intl/DisplayNames/dateTimeField.js | 176 + js/src/tests/non262/Intl/DisplayNames/dayPeriod.js | 80 + .../non262/Intl/DisplayNames/language-dialect.js | 104 + js/src/tests/non262/Intl/DisplayNames/language.js | 205 + .../non262/Intl/DisplayNames/month-calendar.js | 18 + js/src/tests/non262/Intl/DisplayNames/month.js | 104 + js/src/tests/non262/Intl/DisplayNames/quarter.js | 74 + js/src/tests/non262/Intl/DisplayNames/region.js | 157 + js/src/tests/non262/Intl/DisplayNames/script.js | 134 + js/src/tests/non262/Intl/DisplayNames/shell.js | 6 + js/src/tests/non262/Intl/DisplayNames/weekday.js | 77 + js/src/tests/non262/Intl/ListFormat/browser.js | 0 .../non262/Intl/ListFormat/conjunction-type.js | 116 + .../non262/Intl/ListFormat/cross-compartment.js | 42 + .../non262/Intl/ListFormat/disjunction-type.js | 108 + .../non262/Intl/ListFormat/same-compartment.js | 40 + js/src/tests/non262/Intl/ListFormat/shell.js | 21 + .../non262/Intl/ListFormat/supported-locales.js | 18 + js/src/tests/non262/Intl/ListFormat/unit-type.js | 149 + .../apply-options-to-tag-canonicalize-twice.js | 11 + js/src/tests/non262/Intl/Locale/browser.js | 0 .../Locale/coerce-options-before-validating-tag.js | 10 + .../tests/non262/Intl/Locale/cross-compartment.js | 28 + js/src/tests/non262/Intl/Locale/legacy.js | 75 + .../non262/Intl/Locale/likely-subtags-generated.js | 15797 +++++ js/src/tests/non262/Intl/Locale/likely-subtags.js | 61 + .../tests/non262/Intl/Locale/same-compartment.js | 26 + js/src/tests/non262/Intl/Locale/shell.js | 0 js/src/tests/non262/Intl/Locale/surface.js | 98 + .../tests/non262/Intl/NumberFormat/StringBuffer.js | 37 + .../tests/non262/Intl/NumberFormat/bigint-int64.js | 40 + js/src/tests/non262/Intl/NumberFormat/browser.js | 0 js/src/tests/non262/Intl/NumberFormat/call.js | 184 + .../Intl/NumberFormat/construct-newtarget.js | 81 + .../non262/Intl/NumberFormat/cross-compartment.js | 70 + .../Intl/NumberFormat/currency-narrow-symbol.js | 40 + .../Intl/NumberFormat/currency-sign-accounting.js | 192 + .../NumberFormat/duplicate-singleton-variant.js | 49 + .../Intl/NumberFormat/format-as-code-or-name.js | 75 + .../non262/Intl/NumberFormat/format-string.js | 149 + js/src/tests/non262/Intl/NumberFormat/format.js | 55 + .../non262/Intl/NumberFormat/formatRange-BigInt.js | 150 + .../tests/non262/Intl/NumberFormat/formatRange.js | 296 + ...ormatRangeToParts-approximately-sign-compact.js | 34 + ...rmatRangeToParts-approximately-sign-currency.js | 34 + ...ormatRangeToParts-approximately-sign-percent.js | 34 + ...tRangeToParts-approximately-sign-signDisplay.js | 34 + .../formatRangeToParts-approximately-sign-unit.js | 41 + .../formatRangeToParts-approximately-sign.js | 34 + .../non262/Intl/NumberFormat/formatRangeToParts.js | 174 + .../non262/Intl/NumberFormat/formatToParts.js | 357 + .../non262/Intl/NumberFormat/formatting-NaN.js | 35 + .../NumberFormat/negativeZeroFractionDigits.js | 21 + .../Intl/NumberFormat/notation-compact-long.js | 139 + .../Intl/NumberFormat/notation-compact-short.js | 136 + .../notation-compact-with-fraction-digits.js | 17 + .../Intl/NumberFormat/notation-engineering.js | 136 + .../Intl/NumberFormat/notation-scientific.js | 136 + .../Intl/NumberFormat/numberingSystem-format.js | 18 + .../Intl/NumberFormat/numberingSystem-option.js | 60 + .../Intl/NumberFormat/options-emulate-undefined.js | 13 + .../Intl/NumberFormat/remove-unicode-extensions.js | 25 + .../non262/Intl/NumberFormat/rounding-increment.js | 115 + .../non262/Intl/NumberFormat/rounding-mode.js | 287 + .../non262/Intl/NumberFormat/rounding-priority.js | 132 + js/src/tests/non262/Intl/NumberFormat/shell.js | 77 + .../tests/non262/Intl/NumberFormat/sign-display.js | 187 + .../Intl/NumberFormat/significantDigitsOfZero.js | 38 + .../non262/Intl/NumberFormat/supportedLocalesOf.js | 371 + .../tests/non262/Intl/NumberFormat/toStringTag.js | 29 + .../Intl/NumberFormat/trailing-zero-display.js | 98 + .../NumberFormat/unit-compound-combinations.js | 65 + .../unit-formatToParts-has-unit-field.js | 90 + .../non262/Intl/NumberFormat/unit-well-formed.js | 267 + js/src/tests/non262/Intl/NumberFormat/unit.js | 104 + .../tests/non262/Intl/NumberFormat/unwrapping.js | 248 + .../Intl/NumberFormat/use-grouping-bool-string.js | 10 + .../tests/non262/Intl/NumberFormat/use-grouping.js | 101 + js/src/tests/non262/Intl/PluralRules/browser.js | 0 js/src/tests/non262/Intl/PluralRules/call.js | 53 + .../non262/Intl/PluralRules/construct-newtarget.js | 76 + .../non262/Intl/PluralRules/cross-compartment.js | 22 + .../Intl/PluralRules/negativeZeroFractionDigits.js | 21 + .../non262/Intl/PluralRules/number-options.js | 134 + .../tests/non262/Intl/PluralRules/pluralrules.js | 18 + .../resolvedOptions-overridden-species.js | 25 + js/src/tests/non262/Intl/PluralRules/rounding.js | 17 + js/src/tests/non262/Intl/PluralRules/select.js | 63 + .../tests/non262/Intl/PluralRules/selectRange.js | 84 + js/src/tests/non262/Intl/PluralRules/shell.js | 0 .../non262/Intl/PluralRules/supportedLocalesOf.js | 369 + js/src/tests/non262/Intl/README.txt | 27 + .../non262/Intl/RelativeTimeFormat/browser.js | 0 .../Intl/RelativeTimeFormat/construct-newtarget.js | 21 + .../Intl/RelativeTimeFormat/cross-compartment.js | 22 + .../tests/non262/Intl/RelativeTimeFormat/format.js | 145 + .../RelativeTimeFormat/locale-fallback-handling.js | 15 + .../Intl/RelativeTimeFormat/numbering-system.js | 22 + .../RelativeTimeFormat/numberingSystem-option.js | 60 + .../Intl/RelativeTimeFormat/relativetimeformat.js | 15 + .../tests/non262/Intl/RelativeTimeFormat/shell.js | 0 .../Intl/RelativeTimeFormat/supportedLocalesOf.js | 373 + js/src/tests/non262/Intl/Segmenter/browser.js | 0 .../non262/Intl/Segmenter/cross-compartment.js | 35 + .../tests/non262/Intl/Segmenter/grapheme-latin1.js | 37 + js/src/tests/non262/Intl/Segmenter/grapheme.js | 110 + .../non262/Intl/Segmenter/refresh-text-asan.js | 15 + .../tests/non262/Intl/Segmenter/sentence-latin.js | 96 + js/src/tests/non262/Intl/Segmenter/sentence.js | 137 + js/src/tests/non262/Intl/Segmenter/shell.js | 0 .../non262/Intl/Segmenter/surrogate-pair-split.js | 57 + js/src/tests/non262/Intl/Segmenter/word-latin1.js | 215 + js/src/tests/non262/Intl/Segmenter/word.js | 152 + js/src/tests/non262/Intl/String/shell.js | 0 .../tests/non262/Intl/String/toLocaleLowerCase.js | 64 + .../tests/non262/Intl/String/toLocaleUpperCase.js | 64 + js/src/tests/non262/Intl/TypedArray/shell.js | 0 .../tests/non262/Intl/TypedArray/toLocaleString.js | 103 + .../Intl/available-locales-implied-script.js | 35 + .../non262/Intl/available-locales-resolved.js | 41 + .../non262/Intl/available-locales-supported.js | 26 + .../best-available-locale-from-default-locale.js | 107 + js/src/tests/non262/Intl/browser.js | 0 js/src/tests/non262/Intl/default-locale-shell.js | 16 + js/src/tests/non262/Intl/duplicate-variants.js | 46 + js/src/tests/non262/Intl/extensions/browser.js | 0 .../extensions/options-value-emulates-undefined.js | 29 + js/src/tests/non262/Intl/extensions/shell.js | 0 .../Intl/extensions/unicode-extension-sequences.js | 74 + js/src/tests/non262/Intl/fallback-symbol.js | 22 + .../non262/Intl/four-letter-language-codes.js | 22 + js/src/tests/non262/Intl/getCalendarInfo.js | 76 + .../getCanonicalLocales-overridden-arg-length.js | 20 + .../Intl/getCanonicalLocales-overridden-push.js | 16 + .../Intl/getCanonicalLocales-overridden-set.js | 16 + .../Intl/getCanonicalLocales-overridden-species.js | 23 + .../non262/Intl/getCanonicalLocales-weird-cases.js | 25 + .../Intl/getCanonicalLocales-with-duplicates.js | 15 + js/src/tests/non262/Intl/getCanonicalLocales.js | 37 + ...acy-and-sign-locales-with-unicode-extensions.js | 79 + ...esolved-locale-sorted-unicode-extension-keys.js | 109 + js/src/tests/non262/Intl/shell.js | 340 + .../non262/Intl/supportedValuesOf-calendar.js | 25 + .../non262/Intl/supportedValuesOf-collation.js | 44 + .../non262/Intl/supportedValuesOf-currency.js | 24 + .../Intl/supportedValuesOf-numberingSystem.js | 37 + .../Intl/supportedValuesOf-timeZones-canonical.js | 487 + .../non262/Intl/supportedValuesOf-timeZones.js | 20 + js/src/tests/non262/Intl/supportedValuesOf-unit.js | 20 + .../tests/non262/Intl/tolower-ascii-equivalent.js | 47 + .../Intl/unicode-bcp47-locale-ids-extlangs.js | 21 + .../unicode-bcp47-locale-ids-language-mappings.js | 39 + ...-bcp47-locale-ids-languages-mappings-complex.js | 21 + .../non262/Intl/unicode-bcp47-locale-ids-legacy.js | 52 + ...code-bcp47-locale-ids-region-and-subdivision.js | 12 + ...ode-bcp47-locale-ids-region-mappings-complex.js | 57 + .../unicode-bcp47-locale-ids-region-mappings.js | 22 + .../unicode-bcp47-locale-ids-sign-languages.js | 23 + .../unicode-bcp47-locale-ids-transformed-ext.js | 71 + .../Intl/unicode-bcp47-locale-ids-unicode-ext.js | 12 + ...de-bcp47-locale-ids-variants-legacy-mappings.js | 47 + .../unicode-bcp47-locale-ids-variants-sorted.js | 31 + .../non262/Intl/variant-with-preferred-value.js | 58 + .../non262/Iterator/constructor-subclassable.js | 12 + .../constructor-throw-when-called-directly.js | 9 + .../Iterator/constructor-throw-without-new.js | 9 + js/src/tests/non262/Iterator/constructor.js | 9 + .../Iterator/from/Iterator.from-descriptor.js | 12 + .../non262/Iterator/from/Iterator.from-length.js | 17 + .../non262/Iterator/from/Iterator.from-name.js | 13 + .../Iterator/from/call-from-with-different-this.js | 19 + .../Iterator/from/iterator-not-callable-throws.js | 13 + js/src/tests/non262/Iterator/from/modify-next.js | 15 + js/src/tests/non262/Iterator/from/modify-return.js | 22 + .../non262/Iterator/from/o-not-object-throws.js | 13 + .../non262/Iterator/from/proxy-not-wrapped.js | 34 + .../tests/non262/Iterator/from/proxy-wrap-next.js | 30 + .../non262/Iterator/from/proxy-wrap-return.js | 31 + .../Iterator/from/return-iterator-if-iterable.js | 25 + .../from/return-wrapper-if-not-iterable.js | 28 + .../return-wrapper-if-not-iterator-instance.js | 24 + .../from/wrap-functions-on-other-global.js | 29 + .../from/wrap-method-with-non-wrap-this-throws.js | 42 + .../tests/non262/Iterator/from/wrap-new-global.js | 9 + .../Iterator/from/wrap-next-forwards-value.js | 17 + .../Iterator/from/wrap-next-not-object-throws.js | 18 + .../Iterator/from/wrap-return-closes-iterator.js | 34 + js/src/tests/non262/Iterator/iterator.js | 13 + js/src/tests/non262/Iterator/length.js | 13 + js/src/tests/non262/Iterator/name.js | 13 + js/src/tests/non262/Iterator/proto.js | 23 + .../prototype/drop/drop-more-than-available.js | 37 + .../tests/non262/Iterator/prototype/drop/drop.js | 25 + .../tests/non262/Iterator/prototype/drop/length.js | 22 + .../tests/non262/Iterator/prototype/drop/name.js | 19 + .../every/check-fn-after-getting-iterator.js | 25 + .../prototype/every/coerce-result-to-boolean.js | 23 + .../non262/Iterator/prototype/every/descriptor.js | 13 + .../prototype/every/error-from-correct-realm.js | 16 + .../prototype/every/fn-not-callable-throws.js | 15 + .../prototype/every/fn-throws-close-iterator.js | 22 + .../non262/Iterator/prototype/every/length.js | 17 + .../tests/non262/Iterator/prototype/every/name.js | 13 + .../every/next-throws-iterator-not-closed.js | 22 + .../tests/non262/Iterator/prototype/every/proxy.js | 44 + .../prototype/every/return-true-if-all-match.js | 11 + .../prototype/every/short-circuit-on-false.js | 14 + .../prototype/every/this-not-iterator-throws.js | 9 + .../every/value-throws-iterator-not-closed.js | 25 + .../prototype/filter/coerce-result-to-boolean.js | 16 + .../non262/Iterator/prototype/filter/filter.js | 14 + .../non262/Iterator/prototype/filter/length.js | 22 + .../tests/non262/Iterator/prototype/filter/name.js | 19 + .../find/check-fn-after-getting-iterator.js | 25 + .../prototype/find/coerce-result-to-boolean.js | 27 + .../non262/Iterator/prototype/find/descriptor.js | 13 + .../prototype/find/error-from-correct-realm.js | 16 + .../prototype/find/fn-not-callable-throws.js | 15 + .../prototype/find/fn-throws-close-iterator.js | 22 + .../tests/non262/Iterator/prototype/find/length.js | 17 + .../tests/non262/Iterator/prototype/find/name.js | 13 + .../find/next-throws-iterator-not-closed.js | 22 + .../tests/non262/Iterator/prototype/find/proxy.js | 44 + .../find/return-undefined-if-none-match.js | 11 + .../prototype/find/short-circuit-on-match.js | 14 + .../prototype/find/this-not-iterator-throws.js | 9 + .../find/value-throws-iterator-not-closed.js | 25 + .../close-iterator-when-inner-complete-throws.js | 49 + .../close-iterator-when-inner-next-throws.js | 45 + .../close-iterator-when-inner-value-throws.js | 52 + .../non262/Iterator/prototype/flatMap/flatMap.js | 12 + .../prototype/flatMap/inner-empty-iterable.js | 38 + .../Iterator/prototype/flatMap/inner-generator.js | 29 + .../non262/Iterator/prototype/flatMap/length.js | 22 + .../non262/Iterator/prototype/flatMap/name.js | 19 + .../flatMap/throw-when-inner-not-iterable.js | 57 + .../forEach/check-fn-after-getting-iterator.js | 25 + .../Iterator/prototype/forEach/descriptor.js | 13 + .../prototype/forEach/error-from-correct-realm.js | 16 + .../prototype/forEach/fn-not-callable-throws.js | 15 + .../prototype/forEach/fn-throws-close-iterator.js | 22 + .../non262/Iterator/prototype/forEach/forEach.js | 11 + .../non262/Iterator/prototype/forEach/length.js | 17 + .../non262/Iterator/prototype/forEach/name.js | 13 + .../forEach/next-throws-iterator-not-closed.js | 22 + .../non262/Iterator/prototype/forEach/proxy.js | 44 + .../prototype/forEach/this-not-iterator-throws.js | 9 + .../forEach/value-throws-iterator-not-closed.js | 25 + .../generator-methods-throw-on-iterator-helpers.js | 16 + .../iterator-helper-methods-throw-on-generators.js | 14 + .../iterator-helpers-from-other-global.js | 53 + .../prototype/lazy-methods-from-other-global.js | 30 + .../lazy-methods-handle-empty-iterators.js | 39 + .../Iterator/prototype/lazy-methods-interleaved.js | 57 + .../lazy-methods-iterator-closed-on-call-throws.js | 44 + ...lazy-methods-iterator-closed-on-yield-throws.js | 43 + ...y-methods-iterator-not-closed-on-next-throws.js | 43 + ...-methods-iterator-not-closed-on-value-throws.js | 47 + ...ods-iterator-returns-done-generator-finishes.js | 26 + ...-methods-multiple-return-close-iterator-once.js | 59 + .../lazy-methods-pass-through-lastValue.js | 28 + .../lazy-methods-pass-value-through-chain.js | 29 + .../prototype/lazy-methods-proxy-accesses.js | 69 + .../lazy-methods-reentry-not-close-iterator.js | 43 + .../lazy-methods-return-closes-iterator.js | 57 + .../lazy-methods-return-new-iterator-result.js | 38 + ...y-methods-throw-eagerly-on-next-non-callable.js | 33 + .../lazy-methods-throw-eagerly-on-non-callable.js | 38 + .../lazy-methods-throw-eagerly-on-non-iterator.js | 35 + .../lazy-methods-throw-next-done-throws.js | 46 + .../lazy-methods-throw-next-not-object.js | 43 + .../prototype/lazy-methods-throw-on-reentry.js | 18 + .../map/call-next-on-iterator-while-iterating.js | 24 + .../Iterator/prototype/map/clobber-symbol.js | 22 + .../prototype/map/interleaved-map-calls.js | 23 + .../tests/non262/Iterator/prototype/map/length.js | 22 + js/src/tests/non262/Iterator/prototype/map/map.js | 28 + .../prototype/map/mapper-not-callable-throw.js | 33 + .../prototype/map/mutate-iterator-after-done.js | 23 + .../Iterator/prototype/map/mutate-iterator.js | 22 + js/src/tests/non262/Iterator/prototype/map/name.js | 19 + .../prototype/map/output-at-generator-end.js | 26 + .../prototype/map/pass-lastValue-to-next.js | 36 + .../proxy-abrupt-completion-in-iteratorValue.js | 55 + .../map/proxy-abrupt-completion-in-yield.js | 62 + .../prototype/map/proxy-abrupt-completion.js | 54 + .../Iterator/prototype/map/proxy-accesses.js | 94 + .../map/reenter-map-generator-from-mapper.js | 15 + .../prototype/map/this-not-iterator-throw.js | 21 + .../prototype/map/this-value-array-throws.js | 14 + .../map/throw-when-iterator-returns-non-object.js | 24 + .../values-pass-through-chained-maps-to-next.js | 36 + .../reduce/accumulator-set-to-initial-value.js | 9 + .../reduce/check-fn-after-getting-iterator.js | 25 + .../non262/Iterator/prototype/reduce/descriptor.js | 13 + .../empty-iterator-without-initial-value-throws.js | 7 + .../prototype/reduce/error-from-correct-realm.js | 16 + .../reduce/iterator-empty-return-initial-value.js | 9 + .../iterator-next-return-non-object-throws.js | 30 + .../Iterator/prototype/reduce/left-associative.js | 7 + .../non262/Iterator/prototype/reduce/length.js | 17 + .../tests/non262/Iterator/prototype/reduce/name.js | 13 + .../reduce/next-throws-iterator-not-closed.js | 22 + ...initial-value-set-accumulator-to-first-value.js | 9 + .../non262/Iterator/prototype/reduce/proxy.js | 44 + .../non262/Iterator/prototype/reduce/reduce.js | 9 + .../reduce/reducer-not-callable-throws.js | 20 + .../reduce/reducer-throws-iterator-closed.js | 22 + .../prototype/reduce/this-not-iterator-throws.js | 9 + .../reduce/value-throws-iterator-not-closed.js | 25 + .../some/check-fn-after-getting-iterator.js | 25 + .../prototype/some/coerce-result-to-boolean.js | 23 + .../non262/Iterator/prototype/some/descriptor.js | 13 + .../prototype/some/error-from-correct-realm.js | 16 + .../prototype/some/fn-not-callable-throws.js | 15 + .../prototype/some/fn-throws-close-iterator.js | 22 + .../tests/non262/Iterator/prototype/some/length.js | 17 + .../tests/non262/Iterator/prototype/some/name.js | 13 + .../some/next-throws-iterator-not-closed.js | 22 + .../tests/non262/Iterator/prototype/some/proxy.js | 44 + .../prototype/some/return-false-if-none-match.js | 11 + .../prototype/some/short-circuit-on-true.js | 14 + .../prototype/some/this-not-iterator-throws.js | 9 + .../some/value-throws-iterator-not-closed.js | 25 + .../take-drop-throw-eagerly-on-negative.js | 30 + .../take-drop-throw-eagerly-on-non-integer.js | 32 + .../take/close-iterator-when-none-remaining.js | 40 + .../tests/non262/Iterator/prototype/take/length.js | 22 + .../tests/non262/Iterator/prototype/take/name.js | 19 + .../prototype/take/take-more-than-available.js | 52 + .../tests/non262/Iterator/prototype/take/take.js | 25 + .../prototype/toArray/create-in-current-realm.js | 14 + .../Iterator/prototype/toArray/descriptor.js | 13 + .../Iterator/prototype/toArray/iterator-empty.js | 10 + .../non262/Iterator/prototype/toArray/length.js | 17 + .../non262/Iterator/prototype/toArray/name.js | 13 + .../Iterator/prototype/toArray/next-throws.js | 14 + .../non262/Iterator/prototype/toArray/proxy.js | 44 + .../prototype/toArray/this-not-iterator-throws.js | 8 + .../non262/Iterator/prototype/toArray/toArray.js | 17 + .../toArray/value-throws-iterator-not-closed.js | 25 + js/src/tests/non262/JSON/browser.js | 0 .../non262/JSON/cyclic-stringify-unrelated.js | 39 + js/src/tests/non262/JSON/cyclic-stringify.js | 100 + js/src/tests/non262/JSON/immutable-reviver.js | 22 + js/src/tests/non262/JSON/immutable.js | 13 + js/src/tests/non262/JSON/parse-arguments.js | 30 + js/src/tests/non262/JSON/parse-array-gc.js | 34 + js/src/tests/non262/JSON/parse-crockford-01.js | 121 + js/src/tests/non262/JSON/parse-mega-huge-array.js | 28 + js/src/tests/non262/JSON/parse-number-syntax.js | 32 + .../tests/non262/JSON/parse-octal-syntax-error.js | 8 + js/src/tests/non262/JSON/parse-primitives.js | 62 + .../non262/JSON/parse-reviver-array-delete.js | 89 + js/src/tests/non262/JSON/parse-reviver.js | 45 + js/src/tests/non262/JSON/parse-syntax-errors-01.js | 13 + js/src/tests/non262/JSON/parse-syntax-errors-02.js | 43 + js/src/tests/non262/JSON/parse-syntax-errors-03.js | 55 + js/src/tests/non262/JSON/parse-with-source.js | 49 + js/src/tests/non262/JSON/parse.js | 175 + js/src/tests/non262/JSON/regress-458959.js | 29 + js/src/tests/non262/JSON/regress-459293.js | 25 + js/src/tests/non262/JSON/shell.js | 110 + js/src/tests/non262/JSON/small-codepoints.js | 16 + .../non262/JSON/stringify-boxed-primitives.js | 127 + .../non262/JSON/stringify-call-replacer-once.js | 34 + .../non262/JSON/stringify-call-toJSON-once.js | 32 + .../non262/JSON/stringify-dropping-elements.js | 20 + js/src/tests/non262/JSON/stringify-fastpath.js | 212 + js/src/tests/non262/JSON/stringify-gap.js | 61 + .../JSON/stringify-ignore-noncallable-toJSON.js | 28 + .../non262/JSON/stringify-large-replacer-array.js | 26 + .../non262/JSON/stringify-missing-arguments.js | 22 + .../stringify-nonarray-noncallable-replacer.js | 41 + js/src/tests/non262/JSON/stringify-primitives.js | 39 + .../stringify-replacer-array-boxed-elements.js | 60 + .../stringify-replacer-array-duplicated-element.js | 69 + ...ingify-replacer-array-edgecase-jsid-elements.js | 77 + .../JSON/stringify-replacer-array-hijinks.js | 59 + .../stringify-replacer-array-skipped-element.js | 62 + .../stringify-replacer-array-trailing-holes.js | 49 + .../JSON/stringify-replacer-with-array-indexes.js | 56 + js/src/tests/non262/JSON/stringify-replacer.js | 155 + .../tests/non262/JSON/stringify-special-escapes.js | 277 + .../non262/JSON/stringify-toJSON-arguments.js | 34 + js/src/tests/non262/JSON/stringify.js | 87 + js/src/tests/non262/JSON/trailing-comma.js | 32 + js/src/tests/non262/Map/NaN-as-key.js | 55 + js/src/tests/non262/Map/browser.js | 0 .../tests/non262/Map/constructor-iterator-close.js | 293 + .../non262/Map/constructor-iterator-primitive.js | 34 + .../non262/Map/forEach-selfhosted-behavior.js | 51 + js/src/tests/non262/Map/getter-name.js | 10 + js/src/tests/non262/Map/iterable.js | 28 + js/src/tests/non262/Map/iterator-thisv-error.js | 24 + js/src/tests/non262/Map/record-tuple.js | 42 + js/src/tests/non262/Map/shell.js | 0 js/src/tests/non262/Map/symbols.js | 33 + js/src/tests/non262/Math/15.8.1.js | 97 + js/src/tests/non262/Math/15.8.2.13.js | 350 + js/src/tests/non262/Math/15.8.2.16.js | 96 + js/src/tests/non262/Math/15.8.2.17.js | 181 + js/src/tests/non262/Math/15.8.2.18.js | 111 + js/src/tests/non262/Math/15.8.2.2.js | 120 + js/src/tests/non262/Math/15.8.2.3.js | 122 + js/src/tests/non262/Math/15.8.2.4.js | 121 + js/src/tests/non262/Math/15.8.2.5.js | 209 + js/src/tests/non262/Math/15.8.2.7.js | 247 + js/src/tests/non262/Math/15.8.2.8.js | 84 + js/src/tests/non262/Math/20.2.2.ToNumber.js | 112 + js/src/tests/non262/Math/Pow.js | 117 + js/src/tests/non262/Math/acosh-approx.js | 283 + js/src/tests/non262/Math/acosh-exact.js | 26 + js/src/tests/non262/Math/asinh-approx.js | 303 + js/src/tests/non262/Math/asinh-exact.js | 19 + js/src/tests/non262/Math/atanh-approx.js | 280 + js/src/tests/non262/Math/atanh-exact.js | 35 + js/src/tests/non262/Math/browser.js | 0 js/src/tests/non262/Math/cbrt-approx.js | 17 + js/src/tests/non262/Math/cbrt-exact.js | 19 + js/src/tests/non262/Math/clz32.js | 40 + js/src/tests/non262/Math/cosh-approx.js | 276 + js/src/tests/non262/Math/cosh-exact.js | 19 + js/src/tests/non262/Math/exp-exact.js | 29 + js/src/tests/non262/Math/expm1-approx.js | 62 + js/src/tests/non262/Math/expm1-exact.js | 20 + js/src/tests/non262/Math/expm1-monotonicity.js | 94 + js/src/tests/non262/Math/fround.js | 81 + js/src/tests/non262/Math/log10-approx.js | 9 + js/src/tests/non262/Math/log10-exact.js | 30 + js/src/tests/non262/Math/log1p-approx.js | 20 + js/src/tests/non262/Math/log1p-exact.js | 29 + js/src/tests/non262/Math/log2-approx.js | 8 + js/src/tests/non262/Math/log2-exact.js | 30 + js/src/tests/non262/Math/pow-approx-pow10.js | 51 + js/src/tests/non262/Math/pow-approx.js | 568 + js/src/tests/non262/Math/shell.js | 74 + js/src/tests/non262/Math/sign.js | 34 + js/src/tests/non262/Math/sinh-approx.js | 297 + js/src/tests/non262/Math/sinh-exact.js | 19 + js/src/tests/non262/Math/tanh-approx.js | 282 + js/src/tests/non262/Math/tanh-exact.js | 19 + js/src/tests/non262/Math/trunc.js | 50 + .../Number/0x-without-following-hexdigits.js | 30 + js/src/tests/non262/Number/15.7.3.7-EPSILON.js | 24 + js/src/tests/non262/Number/15.7.4.2.js | 31 + .../non262/Number/20.1.2.10-MIN_SAFE_INTEGER.js | 26 + .../non262/Number/20.1.2.6-MAX_SAFE_INTEGER.js | 26 + .../tests/non262/Number/20.1.3.2-toExponential.js | 47 + js/src/tests/non262/Number/20.1.3.2-toPrecision.js | 47 + js/src/tests/non262/Number/20.1.3.3-toFixed.js | 17 + js/src/tests/non262/Number/ToNumber.js | 26 + js/src/tests/non262/Number/browser.js | 0 .../non262/Number/conversion-invalid-precision.js | 46 + js/src/tests/non262/Number/defaultvalue.js | 170 + js/src/tests/non262/Number/isSafeInteger-01.js | 40 + js/src/tests/non262/Number/numericSeparator.js | 10 + js/src/tests/non262/Number/parseFloat-01.js | 27 + js/src/tests/non262/Number/parseInt-01.js | 172 + .../non262/Number/parseInt-default-to-decimal.js | 30 + js/src/tests/non262/Number/regress-442242-01.js | 26 + js/src/tests/non262/Number/shell.js | 0 js/src/tests/non262/Number/toExponential-values.js | 118 + js/src/tests/non262/Number/toFixed-values.js | 118 + js/src/tests/non262/Number/toPrecision-values.js | 100 + .../tests/non262/Number/toString-radix-handling.js | 37 + js/src/tests/non262/Number/tonumber-string-hex.js | 38 + js/src/tests/non262/PrivateName/browser.js | 0 .../tests/non262/PrivateName/constructor-args.js | 23 + js/src/tests/non262/PrivateName/error-locations.js | 34 + .../non262/PrivateName/error-outside-class.js | 13 + .../home-object-when-preceded-by-computed-key.js | 34 + js/src/tests/non262/PrivateName/illegal-delete.js | 94 + .../non262/PrivateName/illegal-in-class-context.js | 32 + .../PrivateName/illegal-in-identifier-context.js | 45 + .../PrivateName/illegal-in-object-context.js | 14 + .../tests/non262/PrivateName/lexical-presence.js | 55 + .../non262/PrivateName/modify-non-extensible.js | 75 + js/src/tests/non262/PrivateName/names.js | 30 + .../non262/PrivateName/nested-class-name-used.js | 32 + js/src/tests/non262/PrivateName/not-iterable.js | 39 + .../PrivateName/parse-utf8-non-ascii-identifier.js | 22 + js/src/tests/non262/PrivateName/prototype-proxy.js | 32 + js/src/tests/non262/PrivateName/proxy-1.js | 21 + js/src/tests/non262/PrivateName/proxy-ccw.js | 66 + js/src/tests/non262/PrivateName/proxy-init-set.js | 74 + .../tests/non262/PrivateName/read-private-eval.js | 13 + js/src/tests/non262/PrivateName/shell.js | 0 js/src/tests/non262/PrivateName/unicode-names.js | 11 + js/src/tests/non262/Promise/allSettled.js | 86 + js/src/tests/non262/Promise/any-stack-overflow.js | 14 + js/src/tests/non262/Promise/any-stack.js | 69 + js/src/tests/non262/Promise/any.js | 76 + js/src/tests/non262/Promise/browser.js | 0 js/src/tests/non262/Promise/bug-1287334.js | 7 + js/src/tests/non262/Promise/bug-1288382.js | 8 + js/src/tests/non262/Promise/bug-1289040.js | 8 + js/src/tests/non262/Promise/bug-1792196.js | 18 + js/src/tests/non262/Promise/dependent-promises.js | 36 + .../non262/Promise/enqueue-promise-reactions.js | 38 + .../non262/Promise/for-of-iterator-uses-getv.js | 25 + .../non262/Promise/get-wait-for-all-promise.js | 60 + js/src/tests/non262/Promise/iterator-close.js | 234 + js/src/tests/non262/Promise/iterator-primitive.js | 28 + .../tests/non262/Promise/methods-non-enumerable.js | 4 + js/src/tests/non262/Promise/promise-all.js | 25 + js/src/tests/non262/Promise/promise-basics.js | 96 + .../promise-rejection-tracking-optimized.js | 34 + .../non262/Promise/promise-rejection-tracking.js | 31 + js/src/tests/non262/Promise/promise-species.js | 8 + js/src/tests/non262/Promise/promise-subclassing.js | 62 + js/src/tests/non262/Promise/self-resolve.js | 40 + js/src/tests/non262/Promise/shell.js | 0 js/src/tests/non262/Promise/withResolvers.js | 25 + js/src/tests/non262/Proxy/browser.js | 0 .../Proxy/define-writable-as-non-writable.js | 19 + js/src/tests/non262/Proxy/delete-non-extensible.js | 18 + js/src/tests/non262/Proxy/getPrototypeOf.js | 285 + js/src/tests/non262/Proxy/global-receiver.js | 35 + js/src/tests/non262/Proxy/hasInstance.js | 13 + ...son-stringify-replacer-array-revocable-proxy.js | 39 + js/src/tests/non262/Proxy/ownkeys-allowed-types.js | 20 + js/src/tests/non262/Proxy/ownkeys-linear.js | 70 + .../tests/non262/Proxy/ownkeys-trap-duplicates.js | 33 + js/src/tests/non262/Proxy/proxy-__proto__.js | 59 + .../tests/non262/Proxy/proxy-constructNonObject.js | 18 + js/src/tests/non262/Proxy/proxy-for-in.js | 37 + .../non262/Proxy/proxy-no-receiver-overwrite.js | 23 + .../tests/non262/Proxy/proxy-proto-lazy-props.js | 61 + .../non262/Proxy/proxy-with-revoked-arguments.js | 53 + js/src/tests/non262/Proxy/regress-bug1037770.js | 7 + js/src/tests/non262/Proxy/regress-bug1062349.js | 31 + js/src/tests/non262/Proxy/regress-bug950407.js | 7 + .../Proxy/report-writable-as-non-writable.js | 20 + .../non262/Proxy/revocable-proxy-prototype.js | 40 + js/src/tests/non262/Proxy/revoke-as-side-effect.js | 73 + js/src/tests/non262/Proxy/revoke-no-name.js | 2 + .../Proxy/revoked-get-function-realm-typeerror.js | 119 + js/src/tests/non262/Proxy/setPrototypeOf.js | 258 + js/src/tests/non262/Proxy/shell.js | 0 js/src/tests/non262/Proxy/trap-null.js | 103 + js/src/tests/non262/ReadableStream/basic-pull.js | 37 + js/src/tests/non262/ReadableStream/basic-push.js | 53 + js/src/tests/non262/ReadableStream/bug-1501502.js | 25 + js/src/tests/non262/ReadableStream/bug-1549768.js | 18 + .../non262/ReadableStream/closed-is-handled.js | 27 + .../non262/ReadableStream/constructor-default.js | 27 + .../ReadableStream/readable-stream-globals.js | 367 + js/src/tests/non262/ReadableStream/shell.js | 30 + js/src/tests/non262/ReadableStream/subclassing.js | 111 + js/src/tests/non262/ReadableStream/tee-start.js | 11 + js/src/tests/non262/Record/browser.js | 0 js/src/tests/non262/Record/constructor.js | 37 + js/src/tests/non262/Record/cross-realm.js | 9 + js/src/tests/non262/Record/enumeration.js | 54 + js/src/tests/non262/Record/equality.js | 23 + js/src/tests/non262/Record/json.js | 13 + js/src/tests/non262/Record/literal.js | 41 + js/src/tests/non262/Record/properties.js | 20 + js/src/tests/non262/Record/property-descriptors.js | 89 + js/src/tests/non262/Record/shell.js | 0 js/src/tests/non262/Record/syntax.js | 27 + js/src/tests/non262/Record/wrapper.js | 25 + js/src/tests/non262/Reflect/apply.js | 130 + js/src/tests/non262/Reflect/argumentsList.js | 164 + js/src/tests/non262/Reflect/browser.js | 0 js/src/tests/non262/Reflect/construct.js | 107 + js/src/tests/non262/Reflect/defineProperty.js | 164 + js/src/tests/non262/Reflect/deleteProperty.js | 80 + js/src/tests/non262/Reflect/get.js | 72 + .../non262/Reflect/getOwnPropertyDescriptor.js | 21 + js/src/tests/non262/Reflect/getPrototypeOf.js | 17 + js/src/tests/non262/Reflect/has.js | 41 + js/src/tests/non262/Reflect/isExtensible.js | 57 + js/src/tests/non262/Reflect/ownKeys.js | 66 + js/src/tests/non262/Reflect/preventExtensions.js | 56 + js/src/tests/non262/Reflect/propertyKeys.js | 84 + js/src/tests/non262/Reflect/set.js | 280 + js/src/tests/non262/Reflect/setPrototypeOf.js | 72 + js/src/tests/non262/Reflect/shell.js | 9 + js/src/tests/non262/Reflect/surfaces.js | 59 + js/src/tests/non262/Reflect/target.js | 44 + js/src/tests/non262/RegExp/15.10.5-01.js | 21 + js/src/tests/non262/RegExp/15.10.6.2-2.js | 292 + js/src/tests/non262/RegExp/15.10.7.5-01.js | 71 + js/src/tests/non262/RegExp/15.5.4.11.js | 498 + js/src/tests/non262/RegExp/7.8.5-01.js | 35 + .../non262/RegExp/RegExpExec-exec-type-check.js | 12 + js/src/tests/non262/RegExp/RegExpExec-exec.js | 18 + js/src/tests/non262/RegExp/RegExpExec-return.js | 31 + js/src/tests/non262/RegExp/RegExp_dollar_number.js | 76 + js/src/tests/non262/RegExp/RegExp_lastMatch.js | 52 + .../non262/RegExp/RegExp_lastMatch_as_array.js | 52 + js/src/tests/non262/RegExp/RegExp_lastParen.js | 66 + .../non262/RegExp/RegExp_lastParen_as_array.js | 66 + js/src/tests/non262/RegExp/RegExp_leftContext.js | 56 + .../non262/RegExp/RegExp_leftContext_as_array.js | 56 + js/src/tests/non262/RegExp/RegExp_object.js | 54 + js/src/tests/non262/RegExp/RegExp_rightContext.js | 56 + .../non262/RegExp/RegExp_rightContext_as_array.js | 56 + js/src/tests/non262/RegExp/browser.js | 0 .../non262/RegExp/character-class-escape-s.js | 54 + ...ter-escape-class-s-mongolian-vowel-separator.js | 25 + js/src/tests/non262/RegExp/class-null.js | 15 + js/src/tests/non262/RegExp/compile-lastIndex.js | 82 + js/src/tests/non262/RegExp/compile-symbol.js | 14 + js/src/tests/non262/RegExp/constructor-IsRegExp.js | 86 + .../tests/non262/RegExp/constructor-constructor.js | 78 + .../tests/non262/RegExp/constructor-ordering-2.js | 21 + js/src/tests/non262/RegExp/constructor-ordering.js | 16 + .../non262/RegExp/constructor-regexp-unicode.js | 9 + js/src/tests/non262/RegExp/constructor-regexp.js | 61 + js/src/tests/non262/RegExp/constructor-symbol.js | 14 + js/src/tests/non262/RegExp/control_characters.js | 39 + .../non262/RegExp/cross-compartment-getter.js | 43 + js/src/tests/non262/RegExp/descriptor.js | 25 + js/src/tests/non262/RegExp/empty-lookahead.js | 8 + js/src/tests/non262/RegExp/escape.js | 70 + js/src/tests/non262/RegExp/everything.js | 47 + js/src/tests/non262/RegExp/exec-002.js | 186 + .../non262/RegExp/exec-lastIndex-ToInteger.js | 36 + .../tests/non262/RegExp/exec-lastIndex-negative.js | 27 + js/src/tests/non262/RegExp/exec.js | 240 + js/src/tests/non262/RegExp/flag-accessors.js | 49 + js/src/tests/non262/RegExp/flags-param-handling.js | 18 + js/src/tests/non262/RegExp/flags.js | 26 + js/src/tests/non262/RegExp/getter-name.js | 16 + js/src/tests/non262/RegExp/ignoreCase-multiple.js | 71 + .../RegExp/ignoreCase-non-latin1-to-latin1.js | 118 + .../instance-property-storage-introspection.js | 128 + js/src/tests/non262/RegExp/lastIndex-exec.js | 80 + .../non262/RegExp/lastIndex-match-or-replace.js | 123 + .../tests/non262/RegExp/lastIndex-nonwritable.js | 27 + js/src/tests/non262/RegExp/lastIndex-search.js | 118 + .../RegExp/match-local-tolength-recompilation.js | 75 + js/src/tests/non262/RegExp/match-this.js | 12 + js/src/tests/non262/RegExp/match-trace.js | 142 + js/src/tests/non262/RegExp/match.js | 36 + js/src/tests/non262/RegExp/multiline-001.js | 67 + js/src/tests/non262/RegExp/octal-001.js | 77 + js/src/tests/non262/RegExp/octal-002.js | 92 + js/src/tests/non262/RegExp/octal-003.js | 86 + js/src/tests/non262/RegExp/oom-in-construction.js | 17 + js/src/tests/non262/RegExp/perlstress-001.js | 3194 + js/src/tests/non262/RegExp/perlstress-002.js | 1806 + js/src/tests/non262/RegExp/properties-001.js | 87 + js/src/tests/non262/RegExp/properties-002.js | 128 + .../non262/RegExp/prototype-different-global.js | 28 + js/src/tests/non262/RegExp/prototype.js | 37 + js/src/tests/non262/RegExp/regexp-enumerate-001.js | 79 + .../non262/RegExp/regexp-space-character-class.js | 27 + js/src/tests/non262/RegExp/regress-001.js | 44 + js/src/tests/non262/RegExp/regress-100199.js | 271 + js/src/tests/non262/RegExp/regress-105972.js | 121 + js/src/tests/non262/RegExp/regress-119909.js | 55 + js/src/tests/non262/RegExp/regress-122076.js | 76 + js/src/tests/non262/RegExp/regress-123437.js | 76 + js/src/tests/non262/RegExp/regress-165353.js | 86 + js/src/tests/non262/RegExp/regress-169497.js | 69 + js/src/tests/non262/RegExp/regress-169534.js | 58 + js/src/tests/non262/RegExp/regress-187133.js | 106 + js/src/tests/non262/RegExp/regress-188206.js | 182 + js/src/tests/non262/RegExp/regress-191479.js | 162 + js/src/tests/non262/RegExp/regress-202564.js | 65 + js/src/tests/non262/RegExp/regress-209067.js | 1069 + js/src/tests/non262/RegExp/regress-209919.js | 138 + js/src/tests/non262/RegExp/regress-216591.js | 81 + js/src/tests/non262/RegExp/regress-220367-001.js | 68 + js/src/tests/non262/RegExp/regress-223273.js | 242 + js/src/tests/non262/RegExp/regress-223535.js | 97 + js/src/tests/non262/RegExp/regress-224676.js | 190 + js/src/tests/non262/RegExp/regress-225289.js | 140 + js/src/tests/non262/RegExp/regress-225343.js | 89 + js/src/tests/non262/RegExp/regress-24712.js | 19 + js/src/tests/non262/RegExp/regress-285219.js | 18 + js/src/tests/non262/RegExp/regress-28686.js | 17 + js/src/tests/non262/RegExp/regress-305064.js | 54 + js/src/tests/non262/RegExp/regress-309840.js | 24 + js/src/tests/non262/RegExp/regress-312351.js | 17 + js/src/tests/non262/RegExp/regress-31316.js | 60 + js/src/tests/non262/RegExp/regress-334158.js | 25 + js/src/tests/non262/RegExp/regress-346090.js | 26 + js/src/tests/non262/RegExp/regress-367888.js | 26 + js/src/tests/non262/RegExp/regress-375642.js | 25 + js/src/tests/non262/RegExp/regress-375651.js | 26 + js/src/tests/non262/RegExp/regress-375711.js | 82 + js/src/tests/non262/RegExp/regress-375715-01-n.js | 27 + js/src/tests/non262/RegExp/regress-375715-02.js | 24 + js/src/tests/non262/RegExp/regress-375715-03.js | 24 + js/src/tests/non262/RegExp/regress-375715-04.js | 32 + js/src/tests/non262/RegExp/regress-429241.js | 200 + js/src/tests/non262/RegExp/regress-436700.js | 31 + js/src/tests/non262/RegExp/regress-465862.js | 80 + js/src/tests/non262/RegExp/regress-57572.js | 114 + js/src/tests/non262/RegExp/regress-57631.js | 115 + js/src/tests/non262/RegExp/regress-576828.js | 8 + js/src/tests/non262/RegExp/regress-613820-1.js | 9 + js/src/tests/non262/RegExp/regress-613820-2.js | 9 + js/src/tests/non262/RegExp/regress-613820-3.js | 9 + js/src/tests/non262/RegExp/regress-617935.js | 42 + js/src/tests/non262/RegExp/regress-6359.js | 52 + js/src/tests/non262/RegExp/regress-67773.js | 175 + js/src/tests/non262/RegExp/regress-72964.js | 85 + js/src/tests/non262/RegExp/regress-76683.js | 78 + js/src/tests/non262/RegExp/regress-78156.js | 87 + js/src/tests/non262/RegExp/regress-87231.js | 109 + js/src/tests/non262/RegExp/regress-9141.js | 71 + js/src/tests/non262/RegExp/regress-98306.js | 63 + js/src/tests/non262/RegExp/regress-yarr-regexp.js | 18 + .../non262/RegExp/replace-compile-elembase.js | 22 + js/src/tests/non262/RegExp/replace-compile.js | 21 + .../tests/non262/RegExp/replace-global-unicode.js | 18 + .../RegExp/replace-local-tolength-lastindex.js | 22 + .../RegExp/replace-local-tolength-recompilation.js | 75 + .../non262/RegExp/replace-sticky-lastIndex.js | 23 + js/src/tests/non262/RegExp/replace-sticky.js | 21 + js/src/tests/non262/RegExp/replace-this.js | 12 + js/src/tests/non262/RegExp/replace-trace.js | 299 + js/src/tests/non262/RegExp/replace-twoBytes.js | 44 + js/src/tests/non262/RegExp/replace.js | 34 + js/src/tests/non262/RegExp/search-this.js | 12 + js/src/tests/non262/RegExp/search-trace.js | 78 + js/src/tests/non262/RegExp/search.js | 26 + js/src/tests/non262/RegExp/shell.js | 256 + js/src/tests/non262/RegExp/source.js | 29 + js/src/tests/non262/RegExp/split-deleted-flags.js | 11 + js/src/tests/non262/RegExp/split-flags-on-obj.js | 21 + .../tests/non262/RegExp/split-invalid-lastIndex.js | 31 + js/src/tests/non262/RegExp/split-limit.js | 14 + js/src/tests/non262/RegExp/split-obj.js | 12 + js/src/tests/non262/RegExp/split-prop-access.js | 19 + js/src/tests/non262/RegExp/split-this.js | 12 + js/src/tests/non262/RegExp/split-trace.js | 229 + js/src/tests/non262/RegExp/split.js | 30 + js/src/tests/non262/RegExp/sticky.js | 126 + js/src/tests/non262/RegExp/test-emptyMatch.js | 23 + js/src/tests/non262/RegExp/test-trailing.js | 31 + js/src/tests/non262/RegExp/toString.js | 42 + .../tests/non262/RegExp/unicode-back-reference.js | 39 + js/src/tests/non262/RegExp/unicode-braced.js | 166 + .../RegExp/unicode-character-class-escape.js | 75 + js/src/tests/non262/RegExp/unicode-class-braced.js | 236 + js/src/tests/non262/RegExp/unicode-class-empty.js | 25 + .../non262/RegExp/unicode-class-ignoreCase.js | 28 + .../non262/RegExp/unicode-class-lead-trail.js | 142 + .../tests/non262/RegExp/unicode-class-negated.js | 64 + js/src/tests/non262/RegExp/unicode-class-range.js | 28 + js/src/tests/non262/RegExp/unicode-class-raw.js | 65 + .../non262/RegExp/unicode-disallow-extended.js | 139 + js/src/tests/non262/RegExp/unicode-everything.js | 59 + .../non262/RegExp/unicode-ignoreCase-ascii.js | 45 + .../non262/RegExp/unicode-ignoreCase-escape.js | 71 + .../non262/RegExp/unicode-ignoreCase-negated.js | 19 + .../RegExp/unicode-ignoreCase-word-boundary.js | 46 + js/src/tests/non262/RegExp/unicode-ignoreCase.js | 2901 + js/src/tests/non262/RegExp/unicode-index.js | 17 + js/src/tests/non262/RegExp/unicode-lead-trail.js | 218 + js/src/tests/non262/RegExp/unicode-raw.js | 139 + js/src/tests/non262/RegExp/yflag.js | 85 + js/src/tests/non262/Scope/browser.js | 0 js/src/tests/non262/Scope/regress-154693.js | 64 + js/src/tests/non262/Scope/regress-181834.js | 146 + js/src/tests/non262/Scope/regress-184107.js | 90 + js/src/tests/non262/Scope/regress-185485.js | 126 + js/src/tests/non262/Scope/regress-191276.js | 91 + js/src/tests/non262/Scope/regress-192226.js | 88 + js/src/tests/non262/Scope/regress-202678-001.js | 99 + js/src/tests/non262/Scope/regress-202678-002.js | 100 + js/src/tests/non262/Scope/regress-208496-001.js | 137 + js/src/tests/non262/Scope/regress-208496-002.js | 129 + js/src/tests/non262/Scope/regress-220362.js | 79 + js/src/tests/non262/Scope/regress-446026-01.js | 51 + js/src/tests/non262/Scope/regress-446026-02.js | 27 + js/src/tests/non262/Scope/regress-77578-001.js | 114 + js/src/tests/non262/Scope/scope-002.js | 105 + js/src/tests/non262/Scope/scope-003.js | 106 + js/src/tests/non262/Scope/scope-004.js | 188 + js/src/tests/non262/Scope/shell.js | 0 js/src/tests/non262/Script/browser.js | 0 js/src/tests/non262/Script/delete-001.js | 46 + js/src/tests/non262/Script/function-002.js | 42 + js/src/tests/non262/Script/in-001.js | 33 + js/src/tests/non262/Script/new-001.js | 79 + js/src/tests/non262/Script/shell.js | 0 js/src/tests/non262/Script/switch-001.js | 48 + js/src/tests/non262/Set/browser.js | 0 js/src/tests/non262/Set/difference.js | 462 + js/src/tests/non262/Set/intersection.js | 478 + js/src/tests/non262/Set/is-disjoint-from.js | 448 + js/src/tests/non262/Set/is-subset-of.js | 333 + js/src/tests/non262/Set/is-superset-of.js | 360 + js/src/tests/non262/Set/shell.js | 102 + js/src/tests/non262/Set/symmetric-difference.js | 303 + js/src/tests/non262/Set/union.js | 300 + js/src/tests/non262/ShadowRealms/ccw-2.js | 22 + js/src/tests/non262/ShadowRealms/ccw.js | 33 + js/src/tests/non262/ShadowRealms/error.js | 102 + ...ction-copy-name-and-length-fails-error-realm.js | 27 + .../tests/non262/ShadowRealms/function-return.js | 73 + .../tests/non262/ShadowRealms/interrupt-request.js | 16 + js/src/tests/non262/ShadowRealms/syntax-error.js | 33 + .../non262/ShadowRealms/unwrap-wrap-with-proto.js | 12 + js/src/tests/non262/String/15.5.4.11-01.js | 66 + js/src/tests/non262/String/15.5.4.2.js | 14 + js/src/tests/non262/String/15.5.4.7.js | 20 + js/src/tests/non262/String/AdvanceStringIndex.js | 43 + js/src/tests/non262/String/IsRegExp.js | 24 + js/src/tests/non262/String/at.js | 38 + js/src/tests/non262/String/browser.js | 0 js/src/tests/non262/String/codePointAt.js | 84 + js/src/tests/non262/String/defaultvalue.js | 169 + js/src/tests/non262/String/fromCodePoint.js | 60 + js/src/tests/non262/String/internalUsage.js | 30 + js/src/tests/non262/String/iterator_edge_cases.js | 27 + ...f-ToNumber-when-searchStr-larger-than-string.js | 22 + .../String/make-normalize-generateddata-input.py | 87 + js/src/tests/non262/String/match-001.js | 104 + js/src/tests/non262/String/match-002.js | 172 + js/src/tests/non262/String/match-003.js | 130 + js/src/tests/non262/String/match-004.js | 172 + js/src/tests/non262/String/match-GetMethod.js | 29 + .../non262/String/match-defines-match-elements.js | 47 + .../tests/non262/String/match-forward-lookahead.js | 27 + .../match-throws-nonwritable-lastIndex-global.js | 88 + .../String/match-updates-global-lastIndex.js | 31 + js/src/tests/non262/String/match.js | 31 + js/src/tests/non262/String/matchAll.js | 288 + .../tests/non262/String/normalize-form-non-atom.js | 18 + .../non262/String/normalize-generateddata-input.js | 19087 ++++++ .../non262/String/normalize-generateddata-part0.js | 22 + .../normalize-generateddata-part1-not-listed.js | 38 + .../non262/String/normalize-generateddata-part1.js | 22 + .../non262/String/normalize-generateddata-part2.js | 22 + .../non262/String/normalize-generateddata-part3.js | 22 + js/src/tests/non262/String/normalize-generic.js | 20 + js/src/tests/non262/String/normalize-parameter.js | 19 + js/src/tests/non262/String/normalize-rope.js | 23 + js/src/tests/non262/String/raw.js | 55 + js/src/tests/non262/String/regress-104375.js | 79 + js/src/tests/non262/String/regress-107771.js | 88 + js/src/tests/non262/String/regress-112626.js | 18 + js/src/tests/non262/String/regress-179068.js | 122 + js/src/tests/non262/String/regress-189898.js | 120 + js/src/tests/non262/String/regress-304376.js | 34 + js/src/tests/non262/String/regress-305064.js | 154 + js/src/tests/non262/String/regress-313567.js | 23 + js/src/tests/non262/String/regress-369778.js | 29 + js/src/tests/non262/String/regress-392378.js | 41 + js/src/tests/non262/String/regress-83293.js | 179 + js/src/tests/non262/String/replace-GetMethod.js | 24 + .../String/replace-bad-dollar-single-quote.js | 61 + js/src/tests/non262/String/replace-flags.js | 25 + js/src/tests/non262/String/replace-math.js | 38 + js/src/tests/non262/String/replace-rope-empty.js | 30 + .../replace-throws-nonwritable-lastIndex-global.js | 126 + .../String/replace-updates-global-lastIndex.js | 38 + js/src/tests/non262/String/replace.js | 19 + js/src/tests/non262/String/replaceAll.js | 215 + js/src/tests/non262/String/ropes.js | 58 + js/src/tests/non262/String/search-GetMethod.js | 24 + js/src/tests/non262/String/search.js | 27 + js/src/tests/non262/String/shell.js | 59 + js/src/tests/non262/String/split-01.js | 47 + js/src/tests/non262/String/split-GetMethod.js | 24 + js/src/tests/non262/String/split-order.js | 22 + .../non262/String/split-undefined-separator.js | 37 + js/src/tests/non262/String/split-xregexp.js | 118 + js/src/tests/non262/String/split.js | 19 + .../string-code-point-upper-lower-mapping.js | 530 + js/src/tests/non262/String/string-object-length.js | 19 + js/src/tests/non262/String/string-pad-start-end.js | 99 + js/src/tests/non262/String/string-space-trim.js | 42 + .../non262/String/string-upper-lower-mapping.js | 65557 ++++++++++++++++++ js/src/tests/non262/String/thisv-error.js | 51 + .../non262/String/two-length-nonlatin-indexOf.js | 11 + js/src/tests/non262/String/unicode-braced.js | 64 + js/src/tests/non262/String/utf8-encode.js | 199 + js/src/tests/non262/String/well-formed.js | 158 + js/src/tests/non262/Symbol/as-base-value.js | 87 + js/src/tests/non262/Symbol/browser.js | 0 js/src/tests/non262/Symbol/comparisons.js | 34 + js/src/tests/non262/Symbol/constructor.js | 35 + js/src/tests/non262/Symbol/conversions.js | 89 + js/src/tests/non262/Symbol/enumeration-order.js | 40 + js/src/tests/non262/Symbol/enumeration.js | 52 + js/src/tests/non262/Symbol/equality.js | 30 + js/src/tests/non262/Symbol/errors.js | 17 + js/src/tests/non262/Symbol/for-in-order.js | 33 + js/src/tests/non262/Symbol/for.js | 31 + js/src/tests/non262/Symbol/json-stringify-keys.js | 19 + .../tests/non262/Symbol/json-stringify-values.js | 33 + js/src/tests/non262/Symbol/keyFor.js | 15 + js/src/tests/non262/Symbol/property-accessor.js | 39 + js/src/tests/non262/Symbol/property-basics.js | 44 + js/src/tests/non262/Symbol/property-inheritance.js | 50 + js/src/tests/non262/Symbol/property-nonwritable.js | 31 + js/src/tests/non262/Symbol/property-reflection.js | 136 + js/src/tests/non262/Symbol/realms.js | 36 + js/src/tests/non262/Symbol/shell.js | 0 js/src/tests/non262/Symbol/species.js | 30 + js/src/tests/non262/Symbol/surfaces.js | 34 + .../symbol-object-not-unboxed-for-value-to-id.js | 31 + .../non262/Symbol/toPrimitive-undefined-or-null.js | 18 + js/src/tests/non262/Symbol/toPrimitive.js | 39 + js/src/tests/non262/Symbol/toString.js | 27 + js/src/tests/non262/Symbol/toStringTag.js | 155 + js/src/tests/non262/Symbol/typed-arrays.js | 17 + js/src/tests/non262/Symbol/typeof.js | 11 + js/src/tests/non262/Symbol/valueOf.js | 22 + js/src/tests/non262/Symbol/well-known.js | 42 + js/src/tests/non262/Temporal/TimeZone/browser.js | 0 .../getPossibleInstantsFor-returns-dead-proxy.js | 21 + js/src/tests/non262/Temporal/TimeZone/shell.js | 0 js/src/tests/non262/Temporal/browser.js | 0 js/src/tests/non262/Temporal/shell.js | 0 js/src/tests/non262/Tuple/4.1.2.11.js | 128 + js/src/tests/non262/Tuple/4.1.2.6.js | 19 + js/src/tests/non262/Tuple/9.1.1.1.js | 12 + js/src/tests/non262/Tuple/browser.js | 0 js/src/tests/non262/Tuple/constructor.js | 18 + js/src/tests/non262/Tuple/constructor/8.2.1.js | 55 + js/src/tests/non262/Tuple/constructor/8.2.2.js | 11 + .../tests/non262/Tuple/constructor/call-method.js | 17 + .../non262/Tuple/constructor/is-a-constructor.js | 4 + js/src/tests/non262/Tuple/constructor/length.js | 13 + js/src/tests/non262/Tuple/constructor/name.js | 20 + js/src/tests/non262/Tuple/cross-realm.js | 22 + js/src/tests/non262/Tuple/elements-literal.js | 22 + js/src/tests/non262/Tuple/elements.js | 19 + js/src/tests/non262/Tuple/enumeration.js | 48 + js/src/tests/non262/Tuple/equality.js | 32 + .../Tuple/from/arraylike-get-length-error.js | 17 + .../non262/Tuple/from/arraylike-to-length-error.js | 17 + .../Tuple/from/calling-from-valid-1-noStrict.js | 43 + .../from/calling-from-valid-1-onlyStrict-strict.js | 44 + .../non262/Tuple/from/calling-from-valid-2.js | 44 + js/src/tests/non262/Tuple/from/descriptor.js | 9 + .../non262/Tuple/from/elements-added-after.js | 29 + .../non262/Tuple/from/elements-deleted-after.js | 24 + js/src/tests/non262/Tuple/from/from.js | 89 + .../tests/non262/Tuple/from/get-iter-method-err.js | 12 + js/src/tests/non262/Tuple/from/indexed-setters.js | 12 + .../non262/Tuple/from/items-is-arraybuffer.js | 8 + .../non262/Tuple/from/items-is-null-throws.js | 5 + js/src/tests/non262/Tuple/from/iter-adv-err.js | 15 + .../tests/non262/Tuple/from/iter-get-iter-err.js | 11 + .../non262/Tuple/from/iter-get-iter-val-err.js | 21 + js/src/tests/non262/Tuple/from/iter-map-fn-args.js | 44 + js/src/tests/non262/Tuple/from/iter-map-fn-err.js | 26 + .../tests/non262/Tuple/from/iter-map-fn-return.js | 44 + .../non262/Tuple/from/iter-map-fn-this-arg.js | 38 + .../Tuple/from/iter-map-fn-this-non-strict.js | 39 + .../Tuple/from/iter-map-fn-this-strict-strict.js | 37 + js/src/tests/non262/Tuple/from/iter-next-error.js | 18 + .../non262/Tuple/from/iter-next-value-error.js | 25 + .../tests/non262/Tuple/from/iter-set-elem-prop.js | 37 + js/src/tests/non262/Tuple/from/iter-set-length.js | 31 + js/src/tests/non262/Tuple/from/length.js | 14 + .../Tuple/from/mapfn-is-not-callable-typeerror.js | 15 + .../non262/Tuple/from/mapfn-throws-exception.js | 12 + js/src/tests/non262/Tuple/from/name.js | 9 + .../tests/non262/Tuple/from/not-a-constructor.js | 9 + js/src/tests/non262/Tuple/from/prop-desc.js | 9 + .../non262/Tuple/from/source-array-boundary.js | 21 + .../non262/Tuple/from/source-object-iterator-1.js | 25 + .../non262/Tuple/from/source-object-length.js | 15 + .../non262/Tuple/from/source-object-without.js | 13 + js/src/tests/non262/Tuple/from/this-null.js | 14 + js/src/tests/non262/Tuple/gc.js | 14 + js/src/tests/non262/Tuple/initializers/6.1.2.1.js | 129 + js/src/tests/non262/Tuple/isTuple/8.2.2.1.js | 54 + js/src/tests/non262/Tuple/isTuple/descriptor.js | 9 + js/src/tests/non262/Tuple/isTuple/length.js | 9 + js/src/tests/non262/Tuple/isTuple/name.js | 9 + .../non262/Tuple/isTuple/not-a-constructor.js | 15 + js/src/tests/non262/Tuple/length-ownproperty.js | 21 + js/src/tests/non262/Tuple/literal.js | 32 + js/src/tests/non262/Tuple/methods.js | 554 + js/src/tests/non262/Tuple/of/length.js | 20 + js/src/tests/non262/Tuple/of/name.js | 9 + js/src/tests/non262/Tuple/of/not-a-constructor.js | 9 + js/src/tests/non262/Tuple/of/of.js | 29 + js/src/tests/non262/Tuple/of/prop-desc.js | 9 + js/src/tests/non262/Tuple/property-descriptors.js | 91 + js/src/tests/non262/Tuple/proto-override.js | 13 + .../Symbol.toStringTag/invoked-as-accessor.js | 22 + .../Tuple/prototype/Symbol.toStringTag/length.js | 11 + .../Tuple/prototype/Symbol.toStringTag/name.js | 7 + .../prototype/Symbol.toStringTag/prop-desc.js | 31 + .../Tuple/prototype/concat/concat-with-array.js | 7 + .../tests/non262/Tuple/prototype/concat/concat.js | 104 + .../Tuple/prototype/concat/indexed-setters.js | 17 + .../tests/non262/Tuple/prototype/concat/length.js | 27 + .../tests/non262/Tuple/prototype/filter/filter.js | 82 + .../Tuple/prototype/filter/indexed-setters.js | 16 + .../tests/non262/Tuple/prototype/filter/length.js | 27 + .../Tuple/prototype/flat/empty-tuple-elements.js | 8 + js/src/tests/non262/Tuple/prototype/flat/flat.js | 96 + .../non262/Tuple/prototype/flat/indexed-setters.js | 16 + js/src/tests/non262/Tuple/prototype/flat/length.js | 27 + .../Tuple/prototype/flat/undefined-elements.js | 10 + .../Tuple/prototype/flatMap/depth-always-one.js | 16 + .../non262/Tuple/prototype/flatMap/flatMap.js | 114 + .../tests/non262/Tuple/prototype/flatMap/length.js | 27 + ...mIndex-equal-or-greater-length-returns-false.js | 13 + .../Tuple/prototype/includes/fromIndex-infinity.js | 23 + .../prototype/includes/fromIndex-minus-zero.js | 24 + .../non262/Tuple/prototype/includes/includes.js | 18 + .../Tuple/prototype/includes/length-internal.js | 14 + .../includes/length-zero-returns-false.js | 23 + .../non262/Tuple/prototype/includes/length.js | 27 + .../tests/non262/Tuple/prototype/includes/name.js | 17 + .../non262/Tuple/prototype/includes/no-arg.js | 12 + .../Tuple/prototype/includes/not-a-constructor.js | 20 + .../non262/Tuple/prototype/includes/prop-desc.js | 14 + .../prototype/includes/return-abrupt-get-length.js | 27 + .../return-abrupt-tointeger-fromindex-symbol.js | 15 + .../includes/return-abrupt-tointeger-fromindex.js | 21 + .../return-abrupt-tonumber-length-symbol.js | 15 + .../Tuple/prototype/includes/samevaluezero.js | 21 + .../includes/search-found-returns-true.js | 28 + .../includes/search-not-found-returns-false.js | 26 + .../Tuple/prototype/includes/this-is-not-tuple.js | 17 + .../prototype/includes/tointeger-fromindex.js | 40 + .../Tuple/prototype/includes/using-fromindex.js | 38 + .../non262/Tuple/prototype/indexOf/empty-tuple.js | 13 + .../Tuple/prototype/indexOf/fromIndex-boolean.js | 14 + .../Tuple/prototype/indexOf/fromIndex-float.js | 15 + .../indexOf/fromIndex-greater-than-length.js | 17 + .../prototype/indexOf/fromIndex-infinity-string.js | 13 + .../indexOf/fromIndex-inherited-valueOf.js | 36 + .../Tuple/prototype/indexOf/fromIndex-missing.js | 17 + .../Tuple/prototype/indexOf/fromIndex-nan.js | 15 + .../prototype/indexOf/fromIndex-neg-infinity.js | 13 + .../Tuple/prototype/indexOf/fromIndex-neg-zero.js | 14 + .../Tuple/prototype/indexOf/fromIndex-negative.js | 16 + .../Tuple/prototype/indexOf/fromIndex-null.js | 15 + .../Tuple/prototype/indexOf/fromIndex-number.js | 14 + .../indexOf/fromIndex-object-not-primitive.js | 33 + .../indexOf/fromIndex-object-valueOf-toString.js | 31 + .../prototype/indexOf/fromIndex-object-valueOf.js | 21 + .../Tuple/prototype/indexOf/fromIndex-object.js | 24 + .../Tuple/prototype/indexOf/fromIndex-positive.js | 16 + .../prototype/indexOf/fromIndex-side-effects-3.js | 23 + .../Tuple/prototype/indexOf/fromIndex-string-2.js | 14 + .../prototype/indexOf/fromIndex-string-exponent.js | 16 + .../prototype/indexOf/fromIndex-string-hex.js | 17 + .../indexOf/fromIndex-string-leading-zeros.js | 16 + .../indexOf/fromIndex-string-neg-infinity.js | 13 + .../prototype/indexOf/fromIndex-string-negative.js | 14 + .../Tuple/prototype/indexOf/fromIndex-string.js | 14 + .../Tuple/prototype/indexOf/fromIndex-trunc-2.js | 17 + .../Tuple/prototype/indexOf/fromIndex-trunc.js | 17 + .../Tuple/prototype/indexOf/fromIndex-undefined.js | 14 + .../prototype/indexOf/fromIndex-with-index.js | 17 + .../Tuple/prototype/indexOf/fromIndex-zero.js | 13 + .../non262/Tuple/prototype/indexOf/includes.js | 18 + .../Tuple/prototype/indexOf/length-internal.js | 14 + .../tests/non262/Tuple/prototype/indexOf/length.js | 27 + .../indexOf/undefined-throws-type-error.js | 18 + .../prototype/indexOf/uses-internal-length.js | 17 + .../non262/Tuple/prototype/isTuple/isTuple.js | 47 + .../tests/non262/Tuple/prototype/isTuple/length.js | 22 + .../tests/non262/Tuple/prototype/join/browser.js | 0 .../non262/Tuple/prototype/join/dda-separator.js | 17 + js/src/tests/non262/Tuple/prototype/join/shell.js | 0 .../non262/Tuple/prototype/length/length-getter.js | 42 + .../prototype/map/callback-not-called-on-empty.js | 7 + .../map/callbackfn-arguments-with-thisarg | 45 + .../map/callbackfn-arguments-with-thisarg.js | 43 + .../map/callbackfn-arguments-without-thisarg.js | 45 + .../prototype/map/callbackfn-is-not-callable.js | 40 + .../prototype/map/callbackfn-returns-abrupt.js | 8 + .../non262/Tuple/prototype/map/indexed-setters.js | 12 + .../non262/Tuple/prototype/map/invoked-as-func.js | 6 + .../Tuple/prototype/map/invoked-as-method.js | 10 + .../non262/Tuple/prototype/map/length-internal.js | 18 + js/src/tests/non262/Tuple/prototype/map/length.js | 27 + js/src/tests/non262/Tuple/prototype/map/map.js | 85 + .../Tuple/prototype/map/this-is-not-tuple.js | 30 + .../Tuple/prototype/slice/invoked-as-func.js | 7 + .../Tuple/prototype/slice/invoked-as-method.js | 9 + .../tests/non262/Tuple/prototype/slice/length.js | 26 + js/src/tests/non262/Tuple/prototype/slice/name.js | 9 + .../non262/Tuple/prototype/slice/negative-zero.js | 10 + .../Tuple/prototype/slice/not-a-constructor.js | 10 + .../non262/Tuple/prototype/slice/prop-desc.js | 9 + .../prototype/slice/return-abrupt-from-end.js | 13 + .../prototype/slice/return-abrupt-from-start.js | 13 + js/src/tests/non262/Tuple/prototype/slice/slice.js | 176 + .../non262/Tuple/prototype/slice/tointeger-end.js | 35 + .../Tuple/prototype/slice/tointeger-start.js | 35 + .../Tuple/prototype/slice/tuple-length-internal.js | 23 + .../Tuple/prototype/toReversed/indexed-setters.js | 16 + .../Tuple/prototype/toReversed/invoked-as-func.js | 10 + .../prototype/toReversed/invoked-as-method.js | 10 + .../non262/Tuple/prototype/toReversed/length.js | 27 + .../prototype/toReversed/this-is-not-tuple.js | 21 + .../Tuple/prototype/toReversed/toReversed.js | 29 + .../prototype/toSorted/comparefn-call-throws.js | 16 + .../Tuple/prototype/toSorted/comparefn-calls.js | 25 + .../toSorted/comparefn-nonfunction-call-throws.js | 25 + .../Tuple/prototype/toSorted/invoked-as-func.js | 10 + .../Tuple/prototype/toSorted/invoked-as-method.js | 10 + .../non262/Tuple/prototype/toSorted/length.js | 27 + .../Tuple/prototype/toSorted/sorted-values.js | 29 + .../non262/Tuple/prototype/toSorted/stability.js | 32 + .../Tuple/prototype/toSorted/this-is-not-tuple.js | 21 + .../non262/Tuple/prototype/toSorted/toSorted.js | 36 + .../toSorted/toSortedcompare-with-no-tostring.js | 14 + .../prototype/toSorted/tuplelength-internal.js | 28 + .../Tuple/prototype/toSpliced/indexed-setters.js | 16 + .../non262/Tuple/prototype/toSpliced/length.js | 27 + .../non262/Tuple/prototype/toSpliced/toSpliced.js | 254 + .../non262/Tuple/prototype/toString/length.js | 27 + .../non262/Tuple/prototype/toString/to-string.js | 21 + .../tests/non262/Tuple/prototype/valueOf/length.js | 15 + .../tests/non262/Tuple/prototype/valueOf/name.js | 9 + .../non262/Tuple/prototype/valueOf/valueOf.js | 23 + js/src/tests/non262/Tuple/prototype/with/with.js | 68 + js/src/tests/non262/Tuple/shell.js | 0 js/src/tests/non262/Tuple/syntax.js | 16 + js/src/tests/non262/Tuple/type-errors.js | 31 + js/src/tests/non262/Tuple/wrapper.js | 25 + .../Tconstructor-fromTypedArray-byteLength.js | 17 + js/src/tests/non262/TypedArray/at.js | 47 + js/src/tests/non262/TypedArray/browser.js | 0 js/src/tests/non262/TypedArray/bug1526838.js | 8 + .../constructor-ArrayBuffer-species-wrap.js | 55 + .../TypedArray/constructor-ArrayBuffer-species.js | 19 + .../TypedArray/constructor-buffer-sequence.js | 230 + .../TypedArray/constructor-byteoffsets-bounds.js | 34 + .../TypedArray/constructor-iterable-generator.js | 16 + ...ructor-iterable-modified-array-iterator-next.js | 28 + ...constructor-iterable-modified-array-iterator.js | 28 + .../constructor-iterable-nonpacked-array.js | 17 + .../constructor-iterable-not-callable.js | 15 + ...onstructor-iterable-packed-array-side-effect.js | 17 + .../constructor-iterable-packed-array.js | 16 + .../constructor-iterable-undefined-or-null.js | 22 + .../TypedArray/constructor-iterator-primitive.js | 29 + .../TypedArray/constructor-length-too-large.js | 40 + .../non262/TypedArray/constructor-non-detached.js | 13 + .../non262/TypedArray/constructor-not-callable.js | 10 + .../constructor-typedarray-species-other-global.js | 33 + .../TypedArray/constructor-undefined-args.js | 14 + .../non262/TypedArray/constructor_bad-args.js | 13 + .../TypedArray/detached-array-buffer-checks.js | 107 + .../element-setting-converts-using-ToNumber.js | 91 + js/src/tests/non262/TypedArray/entries.js | 38 + js/src/tests/non262/TypedArray/every-and-some.js | 249 + js/src/tests/non262/TypedArray/fill-detached.js | 36 + js/src/tests/non262/TypedArray/fill.js | 65 + js/src/tests/non262/TypedArray/filter-species.js | 56 + .../tests/non262/TypedArray/filter-validation.js | 185 + .../tests/non262/TypedArray/find-and-findIndex.js | 52 + .../TypedArray/findLast-and-findLastIndex.js | 52 + js/src/tests/non262/TypedArray/forEach.js | 93 + .../non262/TypedArray/from-iterable-validation.js | 140 + .../TypedArray/from-non-iterable-validation.js | 140 + js/src/tests/non262/TypedArray/from_basics.js | 42 + js/src/tests/non262/TypedArray/from_constructor.js | 36 + js/src/tests/non262/TypedArray/from_errors.js | 76 + js/src/tests/non262/TypedArray/from_iterable.js | 49 + js/src/tests/non262/TypedArray/from_mapping.js | 45 + js/src/tests/non262/TypedArray/from_realms.js | 32 + js/src/tests/non262/TypedArray/from_string.js | 24 + js/src/tests/non262/TypedArray/from_surfaces.js | 12 + js/src/tests/non262/TypedArray/from_this.js | 59 + .../from_typedarray_fastpath_detached.js | 10 + js/src/tests/non262/TypedArray/getter-name.js | 16 + js/src/tests/non262/TypedArray/has-property-op.js | 22 + js/src/tests/non262/TypedArray/includes.js | 40 + .../non262/TypedArray/indexOf-and-lastIndexOf.js | 123 + .../indexOf-never-returns-negative-zero.js | 7 + .../TypedArray/iterator-next-with-detached.js | 73 + js/src/tests/non262/TypedArray/iterator.js | 42 + js/src/tests/non262/TypedArray/join.js | 48 + js/src/tests/non262/TypedArray/keys.js | 36 + js/src/tests/non262/TypedArray/large-arrays.js | 24 + .../lastIndexOf-never-returns-negative-zero.js | 7 + js/src/tests/non262/TypedArray/length.js | 14 + js/src/tests/non262/TypedArray/map-and-filter.js | 274 + js/src/tests/non262/TypedArray/map-species.js | 56 + js/src/tests/non262/TypedArray/map-validation.js | 149 + .../non262/TypedArray/object-defineproperty.js | 68 + js/src/tests/non262/TypedArray/of-validation.js | 140 + js/src/tests/non262/TypedArray/of.js | 92 + .../TypedArray/prototype-constructor-identity.js | 55 + .../non262/TypedArray/reduce-and-reduceRight.js | 188 + js/src/tests/non262/TypedArray/reverse.js | 38 + js/src/tests/non262/TypedArray/seal-and-freeze.js | 49 + .../tests/non262/TypedArray/set-detached-bigint.js | 19 + js/src/tests/non262/TypedArray/set-detached.js | 265 + .../tests/non262/TypedArray/set-negative-offset.js | 35 + ...et-same-buffer-different-source-target-types.js | 41 + js/src/tests/non262/TypedArray/set-tointeger.js | 95 + js/src/tests/non262/TypedArray/set-toobject.js | 53 + .../tests/non262/TypedArray/set-with-receiver.js | 28 + js/src/tests/non262/TypedArray/set-wrapped.js | 81 + js/src/tests/non262/TypedArray/set.js | 21 + js/src/tests/non262/TypedArray/shell.js | 114 + js/src/tests/non262/TypedArray/slice-bitwise.js | 153 + js/src/tests/non262/TypedArray/slice-conversion.js | 515 + js/src/tests/non262/TypedArray/slice-detached.js | 103 + js/src/tests/non262/TypedArray/slice-memcpy.js | 84 + js/src/tests/non262/TypedArray/slice-species.js | 49 + js/src/tests/non262/TypedArray/slice-validation.js | 194 + js/src/tests/non262/TypedArray/slice.js | 45 + .../tests/non262/TypedArray/sort-negative-nan.js | 106 + .../tests/non262/TypedArray/sort-non-function.js | 22 + js/src/tests/non262/TypedArray/sort_basics.js | 73 + js/src/tests/non262/TypedArray/sort_byteoffset.js | 30 + js/src/tests/non262/TypedArray/sort_comparators.js | 32 + js/src/tests/non262/TypedArray/sort_compare_nan.js | 12 + js/src/tests/non262/TypedArray/sort_errors.js | 87 + js/src/tests/non262/TypedArray/sort_globals.js | 9 + .../tests/non262/TypedArray/sort_modifications.js | 73 + .../TypedArray/sort_modifications_concurrent.js | 145 + .../sort_modifications_concurrent_radixsort.js | 116 + js/src/tests/non262/TypedArray/sort_small.js | 38 + js/src/tests/non262/TypedArray/sort_snans.js | 79 + js/src/tests/non262/TypedArray/sort_sorted.js | 30 + js/src/tests/non262/TypedArray/sort_stable.js | 23 + .../non262/TypedArray/sorting_buffer_access.js | 15 + js/src/tests/non262/TypedArray/subarray-species.js | 63 + .../tests/non262/TypedArray/subarray-validation.js | 117 + js/src/tests/non262/TypedArray/subarray.js | 29 + .../TypedArray/test-integrity-level-detached.js | 104 + .../non262/TypedArray/test-integrity-level.js | 67 + .../non262/TypedArray/toLocaleString-detached.js | 38 + .../non262/TypedArray/toLocaleString-nointl.js | 40 + js/src/tests/non262/TypedArray/toLocaleString.js | 80 + .../tests/non262/TypedArray/toReversed-detached.js | 10 + .../tests/non262/TypedArray/toSorted-detached.js | 10 + js/src/tests/non262/TypedArray/toString.js | 69 + .../TypedArray/toStringTag-cross-compartment.js | 12 + .../non262/TypedArray/uint8clamped-constructor.js | 9 + js/src/tests/non262/TypedArray/values.js | 37 + js/src/tests/non262/TypedArray/with-detached.js | 10 + js/src/tests/non262/TypedArray/with.js | 34 + .../TypedArray/write-out-of-bounds-tonumber.js | 60 + js/src/tests/non262/Unicode/browser.js | 0 js/src/tests/non262/Unicode/non-bmp-non-spaces.js | 60 + js/src/tests/non262/Unicode/regress-352044-01.js | 36 + js/src/tests/non262/Unicode/regress-352044-02-n.js | 36 + js/src/tests/non262/Unicode/shell.js | 0 js/src/tests/non262/Unicode/uc-001-n.js | 23 + js/src/tests/non262/Unicode/uc-002-n.js | 14 + js/src/tests/non262/Unicode/uc-002.js | 21 + js/src/tests/non262/Unicode/uc-003.js | 27 + js/src/tests/non262/Unicode/uc-004.js | 26 + js/src/tests/non262/Unicode/uc-005.js | 239 + js/src/tests/non262/WeakMap/browser.js | 0 js/src/tests/non262/WeakMap/shell.js | 0 js/src/tests/non262/WeakMap/symbols.js | 21 + .../non262/WeakMap/symbols_not_as_weakmap_keys.js | 8 + .../arrow-not-as-end-of-statement.js | 188 + ...ing-arrow-with-block-body-followed-by-regexp.js | 15 + js/src/tests/non262/arrow-functions/browser.js | 0 js/src/tests/non262/arrow-functions/shell.js | 0 .../tests/non262/arrow-functions/toString-eof.js | 26 + .../tests/non262/arrow-functions/yield-in-arrow.js | 77 + js/src/tests/non262/async-functions/BoundNames.js | 21 + js/src/tests/non262/async-functions/EarlyErrors.js | 51 + js/src/tests/non262/async-functions/ErrorStack.js | 103 + .../non262/async-functions/arguments_callee.js | 31 + .../async-contains-unicode-escape.js | 54 + .../async-function-declaration-in-modules.js | 13 + .../async-functions/async-property-name-error.js | 21 + js/src/tests/non262/async-functions/await-error.js | 16 + .../async-functions/await-in-arrow-parameters.js | 94 + .../await-in-parameters-of-async-func.js | 67 + .../tests/non262/async-functions/await-newline.js | 15 + js/src/tests/non262/async-functions/browser.js | 0 .../non262/async-functions/construct-newtarget.js | 79 + js/src/tests/non262/async-functions/constructor.js | 33 + .../async-functions/cover-init-name-syntax.js | 65 + .../create-function-parse-before-getprototype.js | 19 + .../non262/async-functions/duplicate-__proto__.js | 22 + .../async-functions/forbidden-as-consequent.js | 14 + js/src/tests/non262/async-functions/identity.js | 14 + .../tests/non262/async-functions/inner-caller.js | 17 + js/src/tests/non262/async-functions/length.js | 12 + js/src/tests/non262/async-functions/methods.js | 61 + .../async-functions/no-expression-closure.js | 17 + .../parameters-error-reject-promise.js | 56 + js/src/tests/non262/async-functions/properties.js | 76 + js/src/tests/non262/async-functions/property.js | 49 + js/src/tests/non262/async-functions/semantics.js | 169 + js/src/tests/non262/async-functions/shell.js | 0 js/src/tests/non262/async-functions/subclass.js | 31 + .../tests/non262/async-functions/syntax-arrow.js | 104 + .../tests/non262/async-functions/syntax-modules.js | 28 + js/src/tests/non262/async-functions/syntax.js | 83 + js/src/tests/non262/async-functions/toSource.js | 26 + js/src/tests/non262/async-functions/toString.js | 24 + js/src/tests/non262/async-functions/yield.js | 71 + js/src/tests/non262/browser.js | 0 .../tests/non262/class/boundFunctionSubclassing.js | 37 + js/src/tests/non262/class/browser.js | 0 .../tests/non262/class/bytecodePatternMatching.js | 29 + .../tests/non262/class/classConstructorNoCall.js | 21 + js/src/tests/non262/class/classHeritage.js | 97 + js/src/tests/non262/class/className.js | 248 + js/src/tests/non262/class/classPrototype.js | 65 + js/src/tests/non262/class/compPropDestr.js | 11 + js/src/tests/non262/class/compPropNames.js | 243 + js/src/tests/non262/class/constructorCalled.js | 45 + .../tests/non262/class/defaultConstructorBase.js | 18 + .../class/defaultConstructorDerivedSpread.js | 23 + .../non262/class/defaultConstructorNotCallable.js | 8 + .../class/derivedConstructorArrowEvalBinding.js | 12 + .../class/derivedConstructorArrowEvalClosed.js | 11 + .../class/derivedConstructorArrowEvalEscape.js | 13 + ...rivedConstructorArrowEvalEscapeUninitialized.js | 38 + .../class/derivedConstructorArrowEvalGetThis.js | 10 + .../derivedConstructorArrowEvalNestedSuperCall.js | 34 + .../class/derivedConstructorArrowEvalSuperCall.js | 18 + .../non262/class/derivedConstructorInlining.js | 19 + .../tests/non262/class/derivedConstructorName.js | 11 + .../class/derivedConstructorReturnPrimitive.js | 15 + .../class/derivedConstructorTDZExplicitThis.js | 12 + .../non262/class/derivedConstructorTDZOffEdge.js | 11 + .../class/derivedConstructorTDZReturnAliasedTry.js | 14 + .../class/derivedConstructorTDZReturnObject.js | 13 + .../non262/class/derivedConstructorTDZReturnTry.js | 16 + .../class/derivedConstructorTDZReturnUndefined.js | 13 + .../non262/class/extendBuiltinConstructors.js | 110 + .../fields-instance-class-name-binding-eval.js | 40 + .../class/fields-instance-class-name-binding.js | 40 + .../class/fields-static-class-name-binding-eval.js | 59 + .../class/fields-static-class-name-binding.js | 59 + js/src/tests/non262/class/geterNoExprClosure.js | 20 + js/src/tests/non262/class/innerBinding.js | 86 + .../tests/non262/class/member-expr-after-super.js | 44 + js/src/tests/non262/class/methDefn.js | 204 + js/src/tests/non262/class/methDefnGen.js | 83 + js/src/tests/non262/class/method-named-static.js | 56 + js/src/tests/non262/class/methodInstallation.js | 101 + js/src/tests/non262/class/methodName.js | 40 + js/src/tests/non262/class/methodOverwrites.js | 80 + js/src/tests/non262/class/methodsPrototype.js | 39 + .../tests/non262/class/newTargetArgumentsIntact.js | 44 + js/src/tests/non262/class/newTargetArrow.js | 24 + js/src/tests/non262/class/newTargetBound.js | 16 + js/src/tests/non262/class/newTargetCCW.js | 10 + js/src/tests/non262/class/newTargetDVG.js | 7 + js/src/tests/non262/class/newTargetDefaults.js | 25 + js/src/tests/non262/class/newTargetDirectInvoke.js | 50 + js/src/tests/non262/class/newTargetEval.js | 40 + js/src/tests/non262/class/newTargetGenerators.js | 14 + js/src/tests/non262/class/newTargetMethods.js | 51 + js/src/tests/non262/class/newTargetNonFunction.js | 10 + js/src/tests/non262/class/newTargetProxyNative.js | 5 + js/src/tests/non262/class/outerBinding.js | 48 + js/src/tests/non262/class/parenExprToString.js | 8 + js/src/tests/non262/class/shell.js | 10 + js/src/tests/non262/class/staticConstructor.js | 22 + js/src/tests/non262/class/staticMethods.js | 15 + js/src/tests/non262/class/strictExecution.js | 38 + js/src/tests/non262/class/stringConstructor.js | 12 + .../tests/non262/class/subclassedArrayUnboxed.js | 22 + .../non262/class/superCallBadDynamicSuperClass.js | 12 + .../non262/class/superCallBadNewTargetPrototype.js | 25 + js/src/tests/non262/class/superCallBaseInvoked.js | 55 + js/src/tests/non262/class/superCallIllegal.js | 7 + js/src/tests/non262/class/superCallInvalidBase.js | 9 + js/src/tests/non262/class/superCallOrder.js | 28 + js/src/tests/non262/class/superCallProperBase.js | 34 + js/src/tests/non262/class/superCallSpreadCall.js | 27 + js/src/tests/non262/class/superCallThisInit.js | 48 + js/src/tests/non262/class/superElemDelete.js | 68 + js/src/tests/non262/class/superPropBasicCalls.js | 27 + js/src/tests/non262/class/superPropBasicChain.js | 11 + js/src/tests/non262/class/superPropBasicGetter.js | 36 + js/src/tests/non262/class/superPropBasicNew.js | 17 + js/src/tests/non262/class/superPropChains.js | 58 + js/src/tests/non262/class/superPropDVG.js | 17 + js/src/tests/non262/class/superPropDelete.js | 64 + js/src/tests/non262/class/superPropDerivedCalls.js | 77 + .../tests/non262/class/superPropDestructuring.js | 43 + .../tests/non262/class/superPropEvalInsideArrow.js | 11 + .../non262/class/superPropEvalInsideNested.js | 13 + js/src/tests/non262/class/superPropFor.js | 25 + .../non262/class/superPropHeavyweightArrow.js | 12 + js/src/tests/non262/class/superPropHomeObject.js | 61 + js/src/tests/non262/class/superPropIncDecElem.js | 24 + .../non262/class/superPropLazyInnerFunction.js | 19 + .../tests/non262/class/superPropNoOverwriting.js | 58 + js/src/tests/non262/class/superPropOrdering.js | 93 + js/src/tests/non262/class/superPropProtoChanges.js | 22 + js/src/tests/non262/class/superPropProxies.js | 83 + js/src/tests/non262/class/superPropSkips.js | 45 + js/src/tests/non262/class/superPropStatics.js | 34 + js/src/tests/non262/class/superPropStrictAssign.js | 23 + .../tests/non262/class/superThisStrictNoBoxing.js | 31 + .../tests/non262/class/uninitializedThisError.js | 53 + js/src/tests/non262/comprehensions/browser.js | 0 js/src/tests/non262/comprehensions/shell.js | 0 .../non262/destructuring/array-default-class.js | 25 + .../non262/destructuring/array-iterator-close.js | 93 + js/src/tests/non262/destructuring/browser.js | 0 js/src/tests/non262/destructuring/bug1396261.js | 44 + .../tests/non262/destructuring/constant-folding.js | 16 + .../non262/destructuring/cover-init-name-syntax.js | 72 + .../non262/destructuring/duplicate-__proto__.js | 54 + .../non262/destructuring/iterator-primitive.js | 36 + js/src/tests/non262/destructuring/order-super.js | 701 + js/src/tests/non262/destructuring/order.js | 719 + .../destructuring/rest-parameter-aray-iterator.js | 40 + .../destructuring/rest-parameter-arguments.js | 101 + .../rest-parameter-function-length.js | 41 + .../rest-parameter-spread-call-optimization.js | 29 + .../non262/destructuring/rest-parameter-syntax.js | 87 + .../tests/non262/destructuring/rest-parameter.js | 54 + .../destructuring/rest-with-trailing-comma.js | 45 + js/src/tests/non262/destructuring/shell.js | 0 .../yield-in-object-destr-function.js | 182 + .../yield-in-object-destr-generator.js | 200 + .../destructuring/yield-in-object-destr-script.js | 123 + .../yield-with-escape-in-object-destr-function.js | 182 + .../yield-with-escape-in-object-destr-generator.js | 200 + .../yield-with-escape-in-object-destr-script.js | 123 + js/src/tests/non262/eval/browser.js | 0 ...xhaustive-fun-normalcaller-direct-normalcode.js | 208 + ...xhaustive-fun-normalcaller-direct-strictcode.js | 210 + ...austive-fun-normalcaller-indirect-normalcode.js | 208 + ...austive-fun-normalcaller-indirect-strictcode.js | 210 + ...xhaustive-fun-strictcaller-direct-normalcode.js | 212 + ...xhaustive-fun-strictcaller-direct-strictcode.js | 214 + ...austive-fun-strictcaller-indirect-normalcode.js | 212 + ...austive-fun-strictcaller-indirect-strictcode.js | 214 + ...ustive-global-normalcaller-direct-normalcode.js | 172 + ...ustive-global-normalcaller-direct-strictcode.js | 174 + ...tive-global-normalcaller-indirect-normalcode.js | 172 + ...tive-global-normalcaller-indirect-strictcode.js | 174 + ...ustive-global-strictcaller-direct-normalcode.js | 173 + ...ustive-global-strictcaller-direct-strictcode.js | 175 + ...tive-global-strictcaller-indirect-normalcode.js | 173 + ...tive-global-strictcaller-indirect-strictcode.js | 175 + .../eval/line-terminator-paragraph-terminator.js | 24 + ...edeclared-arguments-in-param-expression-eval.js | 87 + js/src/tests/non262/eval/regress-531682.js | 32 + js/src/tests/non262/eval/shell.js | 0 .../eval/undeclared-name-in-nested-strict-eval.js | 26 + js/src/tests/non262/execution-contexts/browser.js | 0 .../non262/execution-contexts/regress-23346.js | 31 + .../non262/execution-contexts/regress-448595-01.js | 55 + js/src/tests/non262/execution-contexts/shell.js | 0 js/src/tests/non262/expressions/11.1.5-01.js | 37 + .../non262/expressions/ToPropertyKey-symbols.js | 90 + js/src/tests/non262/expressions/binary-literals.js | 115 + js/src/tests/non262/expressions/browser.js | 0 .../expressions/computed-property-side-effects.js | 35 + .../constant-folded-labeled-statement.js | 14 + .../expressions/delete-constant-folded-and-or.js | 41 + ...e-name-parenthesized-early-error-strict-mode.js | 76 + .../destructuring-array-default-call.js | 10 + .../destructuring-array-default-class.js | 72 + .../destructuring-array-default-function-nested.js | 11 + .../destructuring-array-default-function.js | 11 + .../destructuring-array-default-simple.js | 16 + .../destructuring-array-default-yield.js | 22 + .../non262/expressions/destructuring-array-done.js | 319 + .../expressions/destructuring-array-lexical.js | 12 + .../destructuring-object-__proto__-1.js | 82 + .../destructuring-object-__proto__-2.js | 94 + .../destructuring-pattern-parenthesized.js | 137 + .../non262/expressions/destructuring-scope.js | 67 + .../exponentiation-unparenthesised-unary.js | 106 + .../tests/non262/expressions/inNotObjectError.js | 46 + .../non262/expressions/named-accessor-function.js | 49 + .../expressions/nested-delete-name-in-evalcode.js | 163 + .../tests/non262/expressions/nullish-coalescing.js | 112 + .../non262/expressions/object-literal-__proto__.js | 267 + .../object-literal-accessor-arguments.js | 42 + .../object-literal-accessor-property-name.js | 29 + .../object-literal-computed-property-evaluation.js | 38 + js/src/tests/non262/expressions/octal-literals.js | 103 + .../expressions/optional-chain-class-heritage.js | 10 + .../expressions/optional-chain-first-expression.js | 92 + .../expressions/optional-chain-super-elem.js | 12 + .../tests/non262/expressions/optional-chain-tdz.js | 28 + js/src/tests/non262/expressions/optional-chain.js | 263 + .../expressions/primitive-this-boxing-behavior.js | 106 + js/src/tests/non262/expressions/regress-192288.js | 82 + js/src/tests/non262/expressions/regress-346203.js | 25 + .../tests/non262/expressions/regress-346645-01.js | 31 + .../tests/non262/expressions/regress-346645-02.js | 31 + .../tests/non262/expressions/regress-346645-03.js | 31 + js/src/tests/non262/expressions/regress-394673.js | 49 + js/src/tests/non262/expressions/regress-418051.js | 31 + js/src/tests/non262/expressions/regress-451340.js | 24 + .../non262/expressions/regress-96526-argsub.js | 88 + .../non262/expressions/regress-96526-delelem.js | 88 + .../non262/expressions/regress-96526-noargsub.js | 88 + js/src/tests/non262/expressions/shell.js | 288 + .../short-circuit-compound-assignment-anon-fns.js | 42 + .../short-circuit-compound-assignment-const.js | 90 + ...uit-compound-assignment-deleted-decl-binding.js | 65 + ...-compound-assignment-property-key-evaluation.js | 68 + ...ort-circuit-compound-assignment-scope-lookup.js | 191 + .../short-circuit-compound-assignment-tdz.js | 56 + .../short-circuit-compound-assignment.js | 265 + .../expressions/string-literal-escape-sequences.js | 146 + .../tagged-template-constant-folding.js | 28 + .../non262/expressions/trailing_comma_arguments.js | 85 + .../non262/expressions/trailing_comma_arrow.js | 108 + .../expressions/trailing_comma_getter_setter.js | 88 + .../expressions/trailing_comma_parameters.js | 165 + js/src/tests/non262/extensions/15.9.4.2.js | 56 + js/src/tests/non262/extensions/8.12.5-01.js | 70 + .../ArrayBuffer-slice-arguments-detaching.js | 80 + js/src/tests/non262/extensions/Boolean-toSource.js | 19 + .../DataView-construct-arguments-detaching.js | 80 + .../extensions/DataView-set-arguments-detaching.js | 84 + js/src/tests/non262/extensions/Number-toSource.js | 19 + .../RegExp-error-message-skip-selfhosted-frames.js | 11 + .../tests/non262/extensions/String-match-flags.js | 27 + .../String-methods-infinite-recursion.js | 36 + js/src/tests/non262/extensions/String-toSource.js | 16 + .../TypedArray-set-object-funky-length-detaches.js | 55 + .../TypedArray-subarray-arguments-detaching.js | 111 + js/src/tests/non262/extensions/__proto__.js | 53 + .../arguments-property-access-in-function.js | 58 + .../non262/extensions/array-inherited-__proto__.js | 32 + .../extensions/array-isArray-proxy-recursion.js | 41 + .../non262/extensions/array-length-protochange.js | 35 + js/src/tests/non262/extensions/array-pop-proxy.js | 24 + .../non262/extensions/array-toString-recursion.js | 46 + .../non262/extensions/arraybuffer-prototype.js | 28 + .../non262/extensions/bad-regexp-data-clone.js | 20 + js/src/tests/non262/extensions/basic-for-each.js | 58 + js/src/tests/non262/extensions/basic-for-in.js | 46 + js/src/tests/non262/extensions/browser.js | 6 + js/src/tests/non262/extensions/bug472534.js | 30 + .../builtin-function-arguments-caller.js | 60 + .../non262/extensions/censor-strict-caller.js | 15 + js/src/tests/non262/extensions/clone-bigint.js | 20 + .../non262/extensions/clone-complex-object.js | 312 + js/src/tests/non262/extensions/clone-errors.js | 110 + js/src/tests/non262/extensions/clone-forge.js | 39 + .../extensions/clone-invalid-property-key.js | 22 + .../tests/non262/extensions/clone-leaf-object.js | 68 + .../non262/extensions/clone-many-transferables.js | 25 + .../tests/non262/extensions/clone-object-deep.js | 25 + js/src/tests/non262/extensions/clone-object.js | 143 + js/src/tests/non262/extensions/clone-regexp.js | 36 + .../tests/non262/extensions/clone-sab-failure.js | 39 + js/src/tests/non262/extensions/clone-sab.js | 31 + js/src/tests/non262/extensions/clone-simple.js | 33 + .../tests/non262/extensions/clone-transferables.js | 129 + .../tests/non262/extensions/clone-typed-array.js | 104 + .../extensions/clone-v1-typed-array-data.dat | 32 + .../non262/extensions/clone-v1-typed-array.js | 130 + js/src/tests/non262/extensions/collect-gray.js | 153 + js/src/tests/non262/extensions/column-numbers.js | 10 + .../extensions/cross-global-eval-is-indirect.js | 60 + .../extensions/cross-global-getPrototypeOf.js | 55 + js/src/tests/non262/extensions/dataview.js | 1647 + js/src/tests/non262/extensions/decompile-for-of.js | 27 + .../non262/extensions/destructure-accessor.js | 75 + ...ng-__proto__-shorthand-assignment-before-var.js | 49 + ...destructuring-__proto__-shorthand-assignment.js | 49 + .../destructuring-__proto__-target-assignment.js | 50 + .../extensions/destructuring-for-inof-__proto__.js | 85 + .../tests/non262/extensions/destructuring-order.js | 150 + .../element-setting-ToNumber-detaches.js | 35 + js/src/tests/non262/extensions/empty.txt | 0 .../non262/extensions/error-tostring-function.js | 45 + js/src/tests/non262/extensions/errorcolumnblame.js | 79 + .../extensions/es5ish-defineGetter-defineSetter.js | 281 + .../extensions/eval-native-callback-is-indirect.js | 33 + .../non262/extensions/expression-closure-syntax.js | 62 + ...extension-methods-reject-null-undefined-this.js | 105 + .../non262/extensions/file-mapped-arraybuffers.js | 48 + .../non262/extensions/file-mapped-arraybuffers.txt | 1 + ...al-declaration-and-nested-function-statement.js | 130 + .../function-caller-skips-eval-frames.js | 34 + .../function-caller-strict-cross-global.js | 16 + .../non262/extensions/function-definition-with.js | 56 + .../tests/non262/extensions/function-properties.js | 21 + .../extensions/getOwnPropertyNames-__proto__.js | 26 + js/src/tests/non262/extensions/getset-001.js | 49 + js/src/tests/non262/extensions/getset-003.js | 186 + js/src/tests/non262/extensions/getset-004.js | 174 + js/src/tests/non262/extensions/getset-005.js | 183 + js/src/tests/non262/extensions/getset-006.js | 157 + .../non262/extensions/inc-dec-functioncall.js | 90 + .../keyword-unescaped-requirement-modules.js | 99 + .../extensions/keyword-unescaped-requirement.js | 43 + .../extensions/mutable-proto-special-form.js | 91 + .../extensions/nested-delete-name-in-evalcode.js | 85 + .../non262/extensions/new-cross-compartment.js | 39 + .../non262/extensions/new-parenthesization.js | 21 + .../newer-type-functions-caller-arguments.js | 94 + js/src/tests/non262/extensions/non_syntactic.js | 39 + .../object-toSource-override-on-getter.js | 14 + .../extensions/object-toSource-undefined-getter.js | 11 + .../extensions/object-toSource-with-symbol-keys.js | 16 + .../parse-rest-destructuring-parameter.js | 27 + .../extensions/preventExtensions-cross-global.js | 49 + .../proxy-array-target-length-definition.js | 55 + .../tests/non262/extensions/proxy-enumeration.js | 4 + .../tests/non262/extensions/proxy-proto-setter.js | 50 + js/src/tests/non262/extensions/proxy-strict.js | 12 + .../extensions/quote-string-for-nul-character.js | 94 + js/src/tests/non262/extensions/recursion.js | 60 + .../extensions/redeclaration-of-catch-warning.js | 37 + ...on-and-gc-during-new-RegExp-pattern-ToString.js | 41 + js/src/tests/non262/extensions/regress-103087.js | 141 + js/src/tests/non262/extensions/regress-104077.js | 195 + js/src/tests/non262/extensions/regress-178722.js | 90 + .../tests/non262/extensions/regress-188206-01.js | 71 + .../tests/non262/extensions/regress-188206-02.js | 121 + js/src/tests/non262/extensions/regress-192465.js | 122 + .../tests/non262/extensions/regress-220367-002.js | 75 + js/src/tests/non262/extensions/regress-226078.js | 33 + js/src/tests/non262/extensions/regress-228087.js | 316 + js/src/tests/non262/extensions/regress-245148.js | 20 + js/src/tests/non262/extensions/regress-255245.js | 29 + js/src/tests/non262/extensions/regress-274152.js | 48 + js/src/tests/non262/extensions/regress-300079.js | 42 + js/src/tests/non262/extensions/regress-311161.js | 1440 + .../tests/non262/extensions/regress-311792-01.js | 26 + .../tests/non262/extensions/regress-311792-02.js | 40 + js/src/tests/non262/extensions/regress-313763.js | 46 + js/src/tests/non262/extensions/regress-314874.js | 35 + .../tests/non262/extensions/regress-315509-02.js | 42 + js/src/tests/non262/extensions/regress-319683.js | 31 + js/src/tests/non262/extensions/regress-320854.js | 20 + js/src/tests/non262/extensions/regress-327170.js | 25 + js/src/tests/non262/extensions/regress-327608.js | 42 + js/src/tests/non262/extensions/regress-328443.js | 32 + js/src/tests/non262/extensions/regress-333541.js | 59 + js/src/tests/non262/extensions/regress-336409-1.js | 50 + js/src/tests/non262/extensions/regress-336409-2.js | 49 + js/src/tests/non262/extensions/regress-336410-1.js | 50 + js/src/tests/non262/extensions/regress-336410-2.js | 49 + js/src/tests/non262/extensions/regress-339685.js | 27 + .../tests/non262/extensions/regress-341956-01.js | 65 + .../tests/non262/extensions/regress-341956-02.js | 52 + .../tests/non262/extensions/regress-341956-03.js | 69 + js/src/tests/non262/extensions/regress-342960.js | 43 + .../tests/non262/extensions/regress-346642-06.js | 59 + js/src/tests/non262/extensions/regress-346773.js | 49 + .../tests/non262/extensions/regress-350312-01.js | 43 + js/src/tests/non262/extensions/regress-350312.js | 66 + .../tests/non262/extensions/regress-351070-02.js | 65 + .../tests/non262/extensions/regress-351463-01.js | 250 + js/src/tests/non262/extensions/regress-351973.js | 50 + js/src/tests/non262/extensions/regress-352291.js | 38 + js/src/tests/non262/extensions/regress-352372.js | 62 + js/src/tests/non262/extensions/regress-352604.js | 30 + js/src/tests/non262/extensions/regress-353116.js | 75 + .../tests/non262/extensions/regress-353214-02.js | 27 + js/src/tests/non262/extensions/regress-354297.js | 27 + .../tests/non262/extensions/regress-355052-01.js | 34 + .../tests/non262/extensions/regress-355052-02.js | 34 + .../tests/non262/extensions/regress-355052-03.js | 40 + js/src/tests/non262/extensions/regress-355410.js | 37 + js/src/tests/non262/extensions/regress-355497.js | 58 + .../tests/non262/extensions/regress-363040-01.js | 62 + .../tests/non262/extensions/regress-363040-02.js | 61 + js/src/tests/non262/extensions/regress-363258.js | 45 + js/src/tests/non262/extensions/regress-363988.js | 44 + js/src/tests/non262/extensions/regress-365527.js | 63 + js/src/tests/non262/extensions/regress-365692.js | 40 + js/src/tests/non262/extensions/regress-365869.js | 35 + js/src/tests/non262/extensions/regress-366288.js | 18 + js/src/tests/non262/extensions/regress-366292.js | 19 + js/src/tests/non262/extensions/regress-366396.js | 17 + .../tests/non262/extensions/regress-366668-01.js | 28 + .../tests/non262/extensions/regress-367501-01.js | 32 + .../tests/non262/extensions/regress-367501-02.js | 34 + .../tests/non262/extensions/regress-367501-03.js | 35 + .../tests/non262/extensions/regress-367501-04.js | 35 + js/src/tests/non262/extensions/regress-367589.js | 39 + js/src/tests/non262/extensions/regress-368213.js | 17 + js/src/tests/non262/extensions/regress-368224.js | 25 + js/src/tests/non262/extensions/regress-368516.js | 41 + js/src/tests/non262/extensions/regress-369404.js | 39 + .../tests/non262/extensions/regress-369696-01.js | 30 + .../tests/non262/extensions/regress-369696-02.js | 57 + .../tests/non262/extensions/regress-369696-03.js | 46 + js/src/tests/non262/extensions/regress-372309.js | 37 + js/src/tests/non262/extensions/regress-375183.js | 59 + js/src/tests/non262/extensions/regress-375344.js | 34 + js/src/tests/non262/extensions/regress-379566.js | 44 + js/src/tests/non262/extensions/regress-380889.js | 37 + js/src/tests/non262/extensions/regress-381303.js | 34 + js/src/tests/non262/extensions/regress-381304.js | 69 + .../tests/non262/extensions/regress-385393-02.js | 31 + .../tests/non262/extensions/regress-385393-08.js | 25 + js/src/tests/non262/extensions/regress-390598.js | 31 + js/src/tests/non262/extensions/regress-394967.js | 39 + .../tests/non262/extensions/regress-396326-01.js | 34 + js/src/tests/non262/extensions/regress-396326.js | 45 + js/src/tests/non262/extensions/regress-406572.js | 47 + js/src/tests/non262/extensions/regress-407501.js | 39 + js/src/tests/non262/extensions/regress-407720.js | 44 + js/src/tests/non262/extensions/regress-412926.js | 54 + js/src/tests/non262/extensions/regress-414098.js | 34 + js/src/tests/non262/extensions/regress-414755.js | 51 + js/src/tests/non262/extensions/regress-416354.js | 45 + js/src/tests/non262/extensions/regress-416460.js | 27 + js/src/tests/non262/extensions/regress-416834.js | 20 + .../tests/non262/extensions/regress-420869-01.js | 37 + js/src/tests/non262/extensions/regress-422592.js | 65 + .../tests/non262/extensions/regress-424683-01.js | 33 + js/src/tests/non262/extensions/regress-426711.js | 31 + .../tests/non262/extensions/regress-427196-01.js | 37 + .../tests/non262/extensions/regress-427196-02.js | 34 + .../tests/non262/extensions/regress-427196-03.js | 28 + js/src/tests/non262/extensions/regress-429739.js | 33 + js/src/tests/non262/extensions/regress-430740.js | 36 + .../tests/non262/extensions/regress-434837-01.js | 87 + .../tests/non262/extensions/regress-435497-01.js | 31 + .../tests/non262/extensions/regress-435497-02.js | 31 + .../tests/non262/extensions/regress-435497-03.js | 31 + js/src/tests/non262/extensions/regress-436741.js | 32 + .../tests/non262/extensions/regress-437288-01.js | 32 + js/src/tests/non262/extensions/regress-44009.js | 51 + js/src/tests/non262/extensions/regress-443569.js | 35 + js/src/tests/non262/extensions/regress-446386.js | 44 + js/src/tests/non262/extensions/regress-452168.js | 39 + js/src/tests/non262/extensions/regress-452178.js | 27 + js/src/tests/non262/extensions/regress-452329.js | 24 + js/src/tests/non262/extensions/regress-452338.js | 26 + .../tests/non262/extensions/regress-452498-162.js | 24 + .../tests/non262/extensions/regress-452498-196.js | 32 + js/src/tests/non262/extensions/regress-452565.js | 19 + js/src/tests/non262/extensions/regress-452913.js | 18 + js/src/tests/non262/extensions/regress-453249.js | 21 + js/src/tests/non262/extensions/regress-454744.js | 32 + js/src/tests/non262/extensions/regress-455380.js | 60 + js/src/tests/non262/extensions/regress-455408.js | 26 + js/src/tests/non262/extensions/regress-456826.js | 126 + js/src/tests/non262/extensions/regress-459606.js | 26 + .../tests/non262/extensions/regress-462734-02.js | 26 + .../tests/non262/extensions/regress-462734-03.js | 25 + .../tests/non262/extensions/regress-462734-04.js | 29 + js/src/tests/non262/extensions/regress-465276.js | 29 + js/src/tests/non262/extensions/regress-465337.js | 28 + js/src/tests/non262/extensions/regress-465443.js | 36 + js/src/tests/non262/extensions/regress-465453.js | 38 + .../tests/non262/extensions/regress-466905-04.js | 46 + js/src/tests/non262/extensions/regress-469234.js | 27 + .../tests/non262/extensions/regress-469405-01.js | 27 + .../tests/non262/extensions/regress-469405-02.js | 25 + .../tests/non262/extensions/regress-469625-01.js | 39 + js/src/tests/non262/extensions/regress-469625.js | 28 + js/src/tests/non262/extensions/regress-469761.js | 28 + .../tests/non262/extensions/regress-470300-01.js | 27 + .../tests/non262/extensions/regress-470300-02.js | 27 + js/src/tests/non262/extensions/regress-470310.js | 30 + .../tests/non262/extensions/regress-472450-03.js | 31 + .../tests/non262/extensions/regress-472450-04.js | 33 + js/src/tests/non262/extensions/regress-472599.js | 29 + js/src/tests/non262/extensions/regress-473040.js | 25 + .../tests/non262/extensions/regress-474771-01.js | 29 + .../tests/non262/extensions/regress-474771-02.js | 20 + .../tests/non262/extensions/regress-476414-01.js | 61 + .../tests/non262/extensions/regress-476414-02.js | 61 + js/src/tests/non262/extensions/regress-476447.js | 30 + js/src/tests/non262/extensions/regress-476653.js | 33 + js/src/tests/non262/extensions/regress-476869.js | 42 + js/src/tests/non262/extensions/regress-477158.js | 28 + js/src/tests/non262/extensions/regress-477187.js | 38 + js/src/tests/non262/extensions/regress-479487.js | 41 + js/src/tests/non262/extensions/regress-479551.js | 39 + js/src/tests/non262/extensions/regress-480579.js | 35 + js/src/tests/non262/extensions/regress-481516.js | 38 + js/src/tests/non262/extensions/regress-482263.js | 26 + js/src/tests/non262/extensions/regress-50447-1.js | 179 + js/src/tests/non262/extensions/regress-543839.js | 36 + js/src/tests/non262/extensions/regress-591450.js | 12 + js/src/tests/non262/extensions/regress-636818.js | 9 + js/src/tests/non262/extensions/regress-645160.js | 8 + js/src/tests/non262/extensions/regress-650753.js | 8 + js/src/tests/non262/extensions/regress-696109.js | 13 + .../tests/non262/extensions/regress-90596-001.js | 264 + .../tests/non262/extensions/regress-96284-001.js | 147 + .../tests/non262/extensions/regress-bug607284.js | 16 + .../tests/non262/extensions/regress-bug629723.js | 16 + .../extensions/reviver-mutates-holder-array-ccw.js | 39 + .../reviver-mutates-holder-array-nonnative.js | 46 + .../extensions/reviver-mutates-holder-array.js | 39 + .../reviver-mutates-holder-object-ccw.js | 56 + .../reviver-mutates-holder-object-nonnative.js | 60 + .../extensions/reviver-mutates-holder-object.js | 56 + js/src/tests/non262/extensions/scope-001.js | 84 + .../extensions/set-property-non-extensible.js | 30 + .../non262/extensions/setImmutablePrototype.js | 196 + js/src/tests/non262/extensions/shareddataview.js | 43 + js/src/tests/non262/extensions/sharedtypedarray.js | 273 + js/src/tests/non262/extensions/shell.js | 345 + js/src/tests/non262/extensions/sps-generators.js | 39 + .../string-literal-getter-setter-decompilation.js | 34 + js/src/tests/non262/extensions/toLength.js | 41 + .../toLocaleString-infinite-recursion.js | 31 + .../extensions/toSource-infinite-recursion.js | 36 + ...o-many-arguments-constructing-bound-function.js | 54 + .../typedarray-copyWithin-arguments-detaching.js | 111 + .../non262/extensions/typedarray-set-neutering.js | 45 + .../extensions/typedarray-subarray-of-subarray.js | 33 + js/src/tests/non262/extensions/typedarray.js | 657 + js/src/tests/non262/extensions/uneval/bug496985.js | 14 + js/src/tests/non262/extensions/uneval/bug566661.js | 8 + .../non262/extensions/uneval/function-bind.js | 32 + .../non262/extensions/uneval/regress-231518.js | 99 + .../non262/extensions/uneval/regress-245795.js | 33 + .../non262/extensions/uneval/regress-254375.js | 28 + .../non262/extensions/uneval/regress-304897.js | 22 + .../non262/extensions/uneval/regress-306738.js | 30 + .../non262/extensions/uneval/regress-311583.js | 23 + .../non262/extensions/uneval/regress-313803.js | 29 + .../non262/extensions/uneval/regress-322957.js | 29 + .../non262/extensions/uneval/regress-328556.js | 21 + .../non262/extensions/uneval/regress-358594-01.js | 31 + .../non262/extensions/uneval/regress-358594-02.js | 23 + .../non262/extensions/uneval/regress-358594-03.js | 30 + .../non262/extensions/uneval/regress-358594-04.js | 23 + .../non262/extensions/uneval/regress-358594-05.js | 31 + .../non262/extensions/uneval/regress-358594-06.js | 23 + .../non262/extensions/uneval/regress-367629.js | 45 + .../non262/extensions/uneval/regress-375801.js | 35 + .../non262/extensions/uneval/regress-380581.js | 28 + .../non262/extensions/uneval/regress-380933.js | 29 + .../non262/extensions/uneval/regress-381211.js | 28 + .../non262/extensions/uneval/regress-381301.js | 39 + .../non262/extensions/uneval/regress-385393-03.js | 29 + .../non262/extensions/uneval/regress-385729.js | 58 + .../non262/extensions/uneval/regress-452498-082.js | 33 + .../non262/extensions/uneval/regress-452498-101.js | 30 + .../non262/extensions/uneval/regress-452498-117.js | 35 + .../non262/extensions/uneval/regress-621814.js | 15 + .../non262/extensions/uneval/regress-624199.js | 19 + .../non262/extensions/uneval/regress-90596-002.js | 264 + .../non262/extensions/uneval/regress-96284-002.js | 147 + .../non262/extensions/uneval/regress-bug567606.js | 21 + .../non262/extensions/uneval/symbol-uneval.js | 15 + .../tests/non262/extensions/uneval/toSource-0.js | 16 + .../unterminated-literal-error-location.js | 120 + js/src/tests/non262/extensions/weakmap.js | 121 + .../non262/fields/await-identifier-module-1.js | 3 + .../non262/fields/await-identifier-module-2.js | 3 + .../non262/fields/await-identifier-module-3.js | 3 + .../tests/non262/fields/await-identifier-script.js | 22 + js/src/tests/non262/fields/browser.js | 0 js/src/tests/non262/fields/bug1587574.js | 14 + js/src/tests/non262/fields/init-order.js | 25 + js/src/tests/non262/fields/numeric-fields.js | 14 + js/src/tests/non262/fields/scopes.js | 11 + js/src/tests/non262/fields/shell.js | 0 js/src/tests/non262/fields/unimplemented.js | 57 + js/src/tests/non262/generators/326466-01.js | 45 + js/src/tests/non262/generators/browser.js | 0 .../tests/non262/generators/construct-newtarget.js | 79 + .../create-function-parse-before-getprototype.js | 19 + .../tests/non262/generators/delegating-yield-1.js | 42 + .../tests/non262/generators/delegating-yield-10.js | 49 + .../tests/non262/generators/delegating-yield-11.js | 20 + .../tests/non262/generators/delegating-yield-12.js | 49 + .../tests/non262/generators/delegating-yield-2.js | 73 + .../tests/non262/generators/delegating-yield-3.js | 44 + .../tests/non262/generators/delegating-yield-4.js | 18 + .../tests/non262/generators/delegating-yield-5.js | 37 + .../tests/non262/generators/delegating-yield-6.js | 56 + .../tests/non262/generators/delegating-yield-7.js | 38 + .../tests/non262/generators/delegating-yield-8.js | 44 + .../tests/non262/generators/delegating-yield-9.js | 37 + .../generators/fibonacci-matrix-generator.js | 62 + .../non262/generators/forbidden-as-consequent.js | 11 + .../tests/non262/generators/gen-with-call-obj.js | 36 + js/src/tests/non262/generators/iteration.js | 574 + .../non262/generators/iterator-next-non-object.js | 64 + .../tests/non262/generators/iterator-toString.js | 41 + js/src/tests/non262/generators/nested-yield.js | 44 + js/src/tests/non262/generators/objects.js | 49 + js/src/tests/non262/generators/pi-generator.js | 57 + js/src/tests/non262/generators/properties.js | 111 + js/src/tests/non262/generators/regress-345855.js | 90 + .../tests/non262/generators/regress-345879-01.js | 30 + js/src/tests/non262/generators/regress-349362.js | 26 + js/src/tests/non262/generators/regress-349851.js | 33 + js/src/tests/non262/generators/regress-350809.js | 33 + js/src/tests/non262/generators/regress-351120.js | 33 + js/src/tests/non262/generators/regress-359062.js | 38 + js/src/tests/non262/generators/regress-366941.js | 80 + js/src/tests/non262/generators/regress-384991.js | 56 + js/src/tests/non262/generators/regress-466206.js | 35 + js/src/tests/non262/generators/return-finally.js | 309 + js/src/tests/non262/generators/runtime.js | 132 + js/src/tests/non262/generators/shell.js | 17 + js/src/tests/non262/generators/simple-fib.js | 55 + js/src/tests/non262/generators/subclass.js | 33 + js/src/tests/non262/generators/syntax.js | 140 + js/src/tests/non262/generators/yield-error.js | 32 + .../non262/generators/yield-iterator-close.js | 58 + js/src/tests/non262/generators/yield-non-regexp.js | 16 + .../non262/generators/yield-star-iterator-close.js | 153 + .../generators/yield-star-iterator-primitive.js | 31 + .../non262/generators/yield-star-throw-htmldda.js | 28 + js/src/tests/non262/get-set/browser.js | 0 js/src/tests/non262/get-set/getset-002.js | 48 + js/src/tests/non262/get-set/regress-375976.js | 28 + js/src/tests/non262/get-set/shell.js | 0 .../adding-global-var-nonextensible-error.js | 36 + js/src/tests/non262/global/browser.js | 0 js/src/tests/non262/global/bug-320887.js | 15 + js/src/tests/non262/global/bug660612.js | 7 + .../non262/global/cross-global-implicit-this.js | 84 + .../non262/global/decodeURI-decodes-FFFE-FFFF.js | 26 + .../non262/global/delete-global-NaN-property.js | 32 + js/src/tests/non262/global/direct-eval-but-not.js | 32 + js/src/tests/non262/global/eval-01.js | 38 + js/src/tests/non262/global/eval-02.js | 38 + .../eval-in-strict-eval-in-normal-function.js | 30 + .../non262/global/eval-inside-with-is-direct.js | 28 + .../global/eval-native-callback-is-indirect.js | 32 + .../tests/non262/global/globalThis-enumeration.js | 5 + .../non262/global/parenthesized-eval-is-direct.js | 68 + js/src/tests/non262/global/parseFloat-01.js | 24 + js/src/tests/non262/global/parseInt-01.js | 170 + .../non262/global/parseInt-default-to-decimal.js | 31 + js/src/tests/non262/global/shell.js | 0 js/src/tests/non262/iterable/browser.js | 0 js/src/tests/non262/iterable/regress-340526-01.js | 27 + js/src/tests/non262/iterable/regress-341815.js | 83 + js/src/tests/non262/iterable/regress-341821.js | 72 + js/src/tests/non262/iterable/regress-415922.js | 46 + js/src/tests/non262/iterable/shell.js | 0 js/src/tests/non262/jit/browser.js | 0 js/src/tests/non262/jit/math-jit-tests.js | 535 + js/src/tests/non262/jit/regress-458838.js | 39 + js/src/tests/non262/jit/regress-489682.js | 31 + js/src/tests/non262/jit/shell.js | 0 js/src/tests/non262/lexical-conventions/browser.js | 0 .../non262/lexical-conventions/lexical-001.js | 146 + .../non262/lexical-conventions/regress-177314.js | 73 + .../non262/lexical-conventions/regress-469940.js | 35 + js/src/tests/non262/lexical-conventions/shell.js | 0 .../block-scoped-functions-annex-b-arguments.js | 10 + .../block-scoped-functions-annex-b-eval.js | 51 + .../block-scoped-functions-annex-b-generators.js | 26 + .../block-scoped-functions-annex-b-if.js | 42 + .../block-scoped-functions-annex-b-label.js | 43 + ...block-scoped-functions-annex-b-notapplicable.js | 14 + .../block-scoped-functions-annex-b-parameter.js | 21 + .../block-scoped-functions-annex-b-property.js | 18 + .../block-scoped-functions-annex-b-same-name.js | 7 + .../block-scoped-functions-annex-b-with.js | 18 + .../block-scoped-functions-annex-b.js | 31 + .../block-scoped-functions-deprecated-redecl.js | 78 + .../block-scoped-functions-hoisted-tdz.js | 30 + .../block-scoped-functions-strict.js | 45 + js/src/tests/non262/lexical-environment/browser.js | 0 .../non262/lexical-environment/bug-1216623.js | 19 + .../tests/non262/lexical-environment/catch-body.js | 19 + .../const-declaration-in-for-loop.js | 88 + .../eval-has-lexical-environment.js | 45 + .../eval-nondefinable-function.js | 10 + .../for-loop-with-bindings-added-at-runtime.js | 125 + .../tests/non262/lexical-environment/for-loop.js | 121 + .../lexical-environment/implicit-this-in-with.js | 18 + .../nondefinable-function-same-script.js | 24 + .../redeclaring-global-properties.js | 64 + js/src/tests/non262/lexical-environment/shell.js | 0 .../lexical-environment/unscopables-basics.js | 22 + .../lexical-environment/unscopables-closures.js | 23 + .../lexical-environment/unscopables-const.js | 8 + .../lexical-environment/unscopables-delete.js | 27 + .../lexical-environment/unscopables-getters.js | 41 + .../lexical-environment/unscopables-global.js | 18 + .../lexical-environment/unscopables-ignored.js | 22 + .../non262/lexical-environment/unscopables-miss.js | 7 + .../unscopables-mutation-frozen.js | 18 + .../lexical-environment/unscopables-mutation.js | 44 + .../lexical-environment/unscopables-proto.js | 39 + .../lexical-environment/unscopables-proxy.js | 46 + .../lexical-environment/unscopables-strict.js | 32 + .../non262/lexical-environment/unscopables-tdz.js | 9 + ...var-in-catch-body-annex-b-eval-destructuring.js | 10 + .../var-in-catch-body-annex-b-eval-for-of.js | 12 + .../var-in-catch-body-annex-b-eval.js | 21 + .../var-in-catch-body-annex-b.js | 114 + .../with-global-ignores-global-let-variables.js | 18 + js/src/tests/non262/lexical/browser.js | 0 js/src/tests/non262/lexical/regress-336376-01.js | 322 + js/src/tests/non262/lexical/regress-346642-04.js | 33 + js/src/tests/non262/lexical/regress-351515.js | 94 + js/src/tests/non262/lexical/shell.js | 0 .../literals/numeric/idstart-after-numeric.js | 15 + js/src/tests/non262/literals/numeric/shell.js | 0 js/src/tests/non262/literals/shell.js | 0 js/src/tests/non262/misc/browser.js | 0 js/src/tests/non262/misc/bug1126318.js | 13 + .../builtin-methods-reject-null-undefined-this.js | 156 + js/src/tests/non262/misc/enumerate-undefined.js | 24 + .../tests/non262/misc/error-undefined-message.js | 7 + .../misc/explicit-undefined-optional-argument.js | 34 + .../tests/non262/misc/function-definition-eval.js | 348 + .../non262/misc/function-definition-evaluate.js | 344 + js/src/tests/non262/misc/future-reserved-words.js | 493 + .../non262/misc/getter-setter-outerize-this.js | 21 + .../tests/non262/misc/global-numeric-properties.js | 59 + ...-paragraph-separator-parse-as-lineterminator.js | 51 + .../tests/non262/misc/new-with-non-constructor.js | 32 + .../misc/redeclare-var-non-writable-property.js | 24 + .../non262/misc/regexp-functions-with-undefined.js | 43 + js/src/tests/non262/misc/regress-bug632003.js | 63 + js/src/tests/non262/misc/shell.js | 0 .../misc/syntax-error-end-of-for-head-part.js | 51 + .../tests/non262/misc/unicode-escaped-keyword.js | 22 + .../tests/non262/misc/unicode-identifier-1d17.js | 16 + .../tests/non262/misc/unicode-identifier-82f1.js | 16 + js/src/tests/non262/misc/unnamed-function.js | 42 + .../tests/non262/misc/unwrapped-no-such-method.js | 13 + .../tests/non262/module/await-restricted-nested.js | 6 + js/src/tests/non262/module/browser.js | 0 js/src/tests/non262/module/bug1488117-empty.js | 3 + .../non262/module/bug1488117-import-namespace.js | 3 + js/src/tests/non262/module/bug1488117.js | 14 + js/src/tests/non262/module/bug1689499-a.js | 5 + js/src/tests/non262/module/bug1689499-b.js | 6 + js/src/tests/non262/module/bug1689499-c.js | 8 + js/src/tests/non262/module/bug1689499-x.js | 3 + js/src/tests/non262/module/bug1689499.js | 23 + js/src/tests/non262/module/bug1693261-async.mjs | 7 + js/src/tests/non262/module/bug1693261-c1.mjs | 6 + js/src/tests/non262/module/bug1693261-c2.mjs | 6 + js/src/tests/non262/module/bug1693261-x.mjs | 6 + js/src/tests/non262/module/bug1693261.js | 33 + .../tests/non262/module/module-export-name-star.js | 12 + js/src/tests/non262/module/shell.js | 0 js/src/tests/non262/object/15.2.3.12.js | 46 + js/src/tests/non262/object/15.2.3.14-01.js | 92 + js/src/tests/non262/object/15.2.3.3-01.js | 285 + js/src/tests/non262/object/15.2.3.4-01.js | 30 + js/src/tests/non262/object/15.2.3.4-02.js | 52 + js/src/tests/non262/object/15.2.3.4-03.js | 55 + js/src/tests/non262/object/15.2.3.4-04.js | 31 + js/src/tests/non262/object/15.2.3.5-01.js | 60 + .../non262/object/15.2.3.6-define-over-method.js | 24 + .../15.2.3.6-dictionary-redefinition-01-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-02-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-03-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-04-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-05-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-06-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-07-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-08-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-09-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-10-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-11-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-12-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-13-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-14-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-15-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-16-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-17-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-18-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-19-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-20-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-21-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-22-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-23-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-24-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-25-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-26-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-27-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-28-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-29-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-30-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-31-of-32.js | 6 + .../15.2.3.6-dictionary-redefinition-32-of-32.js | 6 + .../non262/object/15.2.3.6-function-length.js | 35 + .../object/15.2.3.6-middle-redefinition-1-of-8.js | 6 + .../object/15.2.3.6-middle-redefinition-2-of-8.js | 6 + .../object/15.2.3.6-middle-redefinition-3-of-8.js | 6 + .../object/15.2.3.6-middle-redefinition-4-of-8.js | 6 + .../object/15.2.3.6-middle-redefinition-5-of-8.js | 6 + .../object/15.2.3.6-middle-redefinition-6-of-8.js | 6 + .../object/15.2.3.6-middle-redefinition-7-of-8.js | 6 + .../object/15.2.3.6-middle-redefinition-8-of-8.js | 6 + .../tests/non262/object/15.2.3.6-miscellaneous.js | 74 + .../tests/non262/object/15.2.3.6-new-definition.js | 35 + .../non262/object/15.2.3.6-redefinition-1-of-4.js | 39 + .../non262/object/15.2.3.6-redefinition-2-of-4.js | 39 + .../non262/object/15.2.3.6-redefinition-3-of-4.js | 39 + .../non262/object/15.2.3.6-redefinition-4-of-4.js | 39 + js/src/tests/non262/object/15.2.3.7-01.js | 137 + js/src/tests/non262/object/15.2.3.9.js | 51 + .../tests/non262/object/accessor-arguments-rest.js | 24 + js/src/tests/non262/object/accessor-name.js | 35 + .../non262/object/accessor-non-constructor.js | 20 + .../non262/object/add-property-non-extensible.js | 118 + js/src/tests/non262/object/assign.js | 303 + js/src/tests/non262/object/browser.js | 7 + js/src/tests/non262/object/bug-1150906.js | 13 + js/src/tests/non262/object/bug-1206700.js | 10 + .../object/clear-dictionary-accessor-getset.js | 55 + .../non262/object/defineGetter-defineSetter.js | 92 + .../object/defineProperties-callable-accessor.js | 19 + .../tests/non262/object/defineProperties-order.js | 17 + js/src/tests/non262/object/defineProperty-proxy.js | 54 + js/src/tests/non262/object/defineProperty-setup.js | 1071 + .../object/destructuring-shorthand-defaults.js | 127 + js/src/tests/non262/object/duplProps.js | 116 + js/src/tests/non262/object/entries.js | 94 + js/src/tests/non262/object/extensibility-01.js | 103 + js/src/tests/non262/object/extensibility-02.js | 42 + .../non262/object/freeze-global-eval-const.js | 13 + js/src/tests/non262/object/freeze-proxy.js | 27 + js/src/tests/non262/object/freeze.js | 21 + .../non262/object/gOPD-vs-prototype-accessor.js | 15 + .../non262/object/getOwnPropertyDescriptor.js | 35 + .../non262/object/getOwnPropertySymbols-proxy.js | 28 + .../tests/non262/object/getOwnPropertySymbols.js | 46 + js/src/tests/non262/object/getPrototypeOf-array.js | 32 + js/src/tests/non262/object/getPrototypeOf.js | 22 + js/src/tests/non262/object/getter-name.js | 10 + js/src/tests/non262/object/hasOwn.js | 18 + js/src/tests/non262/object/isExtensible.js | 21 + js/src/tests/non262/object/isFrozen.js | 21 + js/src/tests/non262/object/isPrototypeOf.js | 86 + js/src/tests/non262/object/isSealed.js | 21 + js/src/tests/non262/object/keys.js | 23 + .../tests/non262/object/method-non-constructor.js | 12 + .../non262/object/mutation-prevention-methods.js | 124 + .../object-create-with-primitive-second-arg.js | 8 + js/src/tests/non262/object/object-toString-01.js | 46 + .../non262/object/preventExtensions-idempotent.js | 30 + .../tests/non262/object/preventExtensions-proxy.js | 23 + js/src/tests/non262/object/preventExtensions.js | 21 + .../non262/object/property-descriptor-order.js | 17 + .../non262/object/propertyIsEnumerable-proxy.js | 59 + js/src/tests/non262/object/propertyIsEnumerable.js | 199 + .../proto-property-change-writability-set.js | 56 + js/src/tests/non262/object/regress-137000.js | 203 + js/src/tests/non262/object/regress-192105.js | 146 + js/src/tests/non262/object/regress-308806-01.js | 20 + js/src/tests/non262/object/regress-338709.js | 74 + js/src/tests/non262/object/regress-361274.js | 30 + js/src/tests/non262/object/regress-382503.js | 29 + js/src/tests/non262/object/regress-382532.js | 33 + js/src/tests/non262/object/regress-385393-07.js | 31 + js/src/tests/non262/object/regress-444787.js | 101 + js/src/tests/non262/object/regress-459405.js | 37 + js/src/tests/non262/object/regress-465476.js | 60 + js/src/tests/non262/object/regress-72773.js | 60 + js/src/tests/non262/object/regress-79129-001.js | 44 + js/src/tests/non262/object/regress-90596-003.js | 275 + js/src/tests/non262/object/seal-proxy.js | 27 + js/src/tests/non262/object/seal.js | 21 + .../object/setPrototypeOf-cross-realm-cycle.js | 11 + js/src/tests/non262/object/setPrototypeOf-cycle.js | 16 + .../non262/object/setPrototypeOf-same-value.js | 11 + js/src/tests/non262/object/shell.js | 62 + js/src/tests/non262/object/toLocaleString-01.js | 13 + js/src/tests/non262/object/toLocaleString.js | 102 + js/src/tests/non262/object/toPrimitive-callers.js | 57 + js/src/tests/non262/object/toPrimitive.js | 101 + .../object/vacuous-accessor-unqualified-name.js | 26 + .../tests/non262/object/values-entries-indexed.js | 71 + .../non262/object/values-entries-lazy-props.js | 93 + .../non262/object/values-entries-typedarray.js | 53 + js/src/tests/non262/object/values.js | 94 + js/src/tests/non262/operators/11.13.1-001.js | 115 + js/src/tests/non262/operators/11.13.1-002.js | 24 + js/src/tests/non262/operators/11.4.1-001.js | 83 + js/src/tests/non262/operators/11.4.1-002.js | 36 + js/src/tests/non262/operators/browser.js | 0 .../instanceof-bound-function-recursion.js | 23 + js/src/tests/non262/operators/order-01.js | 72 + js/src/tests/non262/operators/shell.js | 0 js/src/tests/non262/reflect-parse/Match.js | 242 + .../tests/non262/reflect-parse/PatternAsserts.js | 95 + .../tests/non262/reflect-parse/PatternBuilders.js | 290 + js/src/tests/non262/reflect-parse/async.js | 25 + js/src/tests/non262/reflect-parse/browser.js | 0 js/src/tests/non262/reflect-parse/class-fields.js | 23 + js/src/tests/non262/reflect-parse/class-static.js | 8 + js/src/tests/non262/reflect-parse/classes.js | 551 + .../non262/reflect-parse/computedPropNames.js | 45 + js/src/tests/non262/reflect-parse/declarations.js | 97 + .../destructuring-array-holes-reflect-as-null.js | 9 + .../reflect-parse/destructuring-assignment.js | 32 + .../destructuring-function-parameters.js | 45 + .../destructuring-variable-declarations.js | 58 + .../non262/reflect-parse/destructuring__proto__.js | 16 + ...expression-short-circuit-compound-assignment.js | 11 + js/src/tests/non262/reflect-parse/expression.js | 193 + .../non262/reflect-parse/for-loop-destructuring.js | 47 + js/src/tests/non262/reflect-parse/generators.js | 12 + js/src/tests/non262/reflect-parse/lexicals.js | 19 + js/src/tests/non262/reflect-parse/location.js | 33 + js/src/tests/non262/reflect-parse/methodDefn.js | 51 + .../non262/reflect-parse/module-export-name.js | 121 + js/src/tests/non262/reflect-parse/newTarget.js | 42 + js/src/tests/non262/reflect-parse/object-rest.js | 41 + js/src/tests/non262/reflect-parse/object-spread.js | 29 + js/src/tests/non262/reflect-parse/proxyArgs.js | 13 + js/src/tests/non262/reflect-parse/shell.js | 66 + js/src/tests/non262/reflect-parse/stackOverflow.js | 8 + js/src/tests/non262/reflect-parse/statements.js | 88 + .../tests/non262/reflect-parse/templateStrings.js | 42 + js/src/tests/non262/regress/browser.js | 0 js/src/tests/non262/regress/regress-102725.js | 61 + js/src/tests/non262/regress/regress-10278.js | 45 + js/src/tests/non262/regress/regress-104077.js | 470 + js/src/tests/non262/regress/regress-110286.js | 119 + js/src/tests/non262/regress/regress-111557.js | 10931 ++++ js/src/tests/non262/regress/regress-114491.js | 69 + js/src/tests/non262/regress/regress-114493.js | 77 + js/src/tests/non262/regress/regress-116228.js | 24 + js/src/tests/non262/regress/regress-118849.js | 149 + js/src/tests/non262/regress/regress-131510-001.js | 40 + js/src/tests/non262/regress/regress-1383630.js | 827 + js/src/tests/non262/regress/regress-139316.js | 46 + js/src/tests/non262/regress/regress-140852.js | 32 + js/src/tests/non262/regress/regress-140974.js | 103 + .../regress/regress-1456512-greyreadbarrier.js | 9 + js/src/tests/non262/regress/regress-1456512.js | 21 + .../non262/regress/regress-1456518-workergray.js | 7 + js/src/tests/non262/regress/regress-1463421.js | 31 + js/src/tests/non262/regress/regress-146596.js | 121 + .../regress/regress-1466387-worker-grayroot.js | 28 + .../non262/regress/regress-1476383-calloc-exc.js | 12 + .../non262/regress/regress-1507322-deep-weakmap.js | 11 + js/src/tests/non262/regress/regress-152646.js | 90 + js/src/tests/non262/regress/regress-155081-2.js | 17520 +++++ js/src/tests/non262/regress/regress-155081.js | 17527 +++++ js/src/tests/non262/regress/regress-156354.js | 94 + .../regress-1572988-nurseryRegisterCheck.js | 38 + js/src/tests/non262/regress/regress-159334.js | 92 + js/src/tests/non262/regress/regress-162392.js | 32 + js/src/tests/non262/regress/regress-165201.js | 55 + js/src/tests/non262/regress/regress-167328.js | 26 + js/src/tests/non262/regress/regress-167658.js | 28 + js/src/tests/non262/regress/regress-168347.js | 183 + js/src/tests/non262/regress/regress-170193.js | 74 + js/src/tests/non262/regress/regress-1707974.js | 30 + .../non262/regress/regress-1714532-oom-gc-yield.js | 9 + js/src/tests/non262/regress/regress-172699.js | 69 + js/src/tests/non262/regress/regress-174709.js | 69 + js/src/tests/non262/regress/regress-176125.js | 49 + js/src/tests/non262/regress/regress-179524.js | 292 + js/src/tests/non262/regress/regress-185165.js | 64 + js/src/tests/non262/regress/regress-191633.js | 70 + js/src/tests/non262/regress/regress-191668.js | 67 + js/src/tests/non262/regress/regress-192414.js | 85 + js/src/tests/non262/regress/regress-193418.js | 67 + js/src/tests/non262/regress/regress-203278-1.js | 30 + js/src/tests/non262/regress/regress-203402.js | 58 + js/src/tests/non262/regress/regress-203841.js | 127 + js/src/tests/non262/regress/regress-204210.js | 116 + js/src/tests/non262/regress/regress-210682.js | 64 + js/src/tests/non262/regress/regress-211590.js | 54 + js/src/tests/non262/regress/regress-214761.js | 44 + js/src/tests/non262/regress/regress-216320.js | 1006 + js/src/tests/non262/regress/regress-224956.js | 248 + js/src/tests/non262/regress/regress-229006.js | 65563 +++++++++++++++++++ js/src/tests/non262/regress/regress-230216-1.js | 47 + js/src/tests/non262/regress/regress-230216-2.js | 39 + js/src/tests/non262/regress/regress-230216-3.js | 46 + js/src/tests/non262/regress/regress-233483-2.js | 59 + js/src/tests/non262/regress/regress-233483.js | 44 + js/src/tests/non262/regress/regress-234389.js | 39 + js/src/tests/non262/regress/regress-238881.js | 30 + js/src/tests/non262/regress/regress-238945.js | 18 + js/src/tests/non262/regress/regress-243174.js | 21 + js/src/tests/non262/regress/regress-243389-n.js | 24 + js/src/tests/non262/regress/regress-243869.js | 38 + js/src/tests/non262/regress/regress-244470.js | 1080 + js/src/tests/non262/regress/regress-244619.js | 32 + js/src/tests/non262/regress/regress-245113.js | 47 + js/src/tests/non262/regress/regress-245308.js | 27 + js/src/tests/non262/regress/regress-246911.js | 30 + js/src/tests/non262/regress/regress-246964.js | 160 + js/src/tests/non262/regress/regress-247179.js | 18 + js/src/tests/non262/regress/regress-248444.js | 31 + js/src/tests/non262/regress/regress-252892.js | 68 + js/src/tests/non262/regress/regress-254296.js | 26 + js/src/tests/non262/regress/regress-254974.js | 38 + js/src/tests/non262/regress/regress-256501.js | 38 + js/src/tests/non262/regress/regress-256617.js | 35 + js/src/tests/non262/regress/regress-256798.js | 36 + js/src/tests/non262/regress/regress-259935.js | 42 + js/src/tests/non262/regress/regress-260541.js | 21 + js/src/tests/non262/regress/regress-261886.js | 29 + js/src/tests/non262/regress/regress-261887.js | 36 + js/src/tests/non262/regress/regress-271716-n.js | 27 + js/src/tests/non262/regress/regress-274035.js | 29 + js/src/tests/non262/regress/regress-274888.js | 35 + js/src/tests/non262/regress/regress-275378.js | 47 + js/src/tests/non262/regress/regress-276103.js | 26 + js/src/tests/non262/regress/regress-278873.js | 27 + js/src/tests/non262/regress/regress-280769-1.js | 27 + js/src/tests/non262/regress/regress-280769-2.js | 44 + js/src/tests/non262/regress/regress-280769-3.js | 45 + js/src/tests/non262/regress/regress-280769-4.js | 47 + js/src/tests/non262/regress/regress-280769-5.js | 34 + js/src/tests/non262/regress/regress-280769.js | 39 + js/src/tests/non262/regress/regress-281606.js | 46 + js/src/tests/non262/regress/regress-281930.js | 20 + js/src/tests/non262/regress/regress-283477.js | 24 + js/src/tests/non262/regress/regress-288688.js | 47 + js/src/tests/non262/regress/regress-289094.js | 27 + js/src/tests/non262/regress/regress-290575.js | 57 + js/src/tests/non262/regress/regress-290656.js | 32 + js/src/tests/non262/regress/regress-294191.js | 29 + js/src/tests/non262/regress/regress-294195-01.js | 25 + js/src/tests/non262/regress/regress-294195-02.js | 17 + js/src/tests/non262/regress/regress-294302.js | 24 + js/src/tests/non262/regress/regress-295052.js | 26 + js/src/tests/non262/regress/regress-295666.js | 22 + js/src/tests/non262/regress/regress-299209.js | 23 + js/src/tests/non262/regress/regress-299641.js | 24 + js/src/tests/non262/regress/regress-303213.js | 56 + js/src/tests/non262/regress/regress-306633.js | 26 + js/src/tests/non262/regress/regress-306794.js | 25 + js/src/tests/non262/regress/regress-308085.js | 569 + js/src/tests/non262/regress/regress-310295.js | 21 + js/src/tests/non262/regress/regress-310607.js | 29 + js/src/tests/non262/regress/regress-310993.js | 22 + js/src/tests/non262/regress/regress-311071.js | 18 + js/src/tests/non262/regress/regress-311157-01.js | 24 + js/src/tests/non262/regress/regress-311157-02.js | 24 + js/src/tests/non262/regress/regress-311629.js | 22 + js/src/tests/non262/regress/regress-31255.js | 76 + js/src/tests/non262/regress/regress-312588.js | 27 + js/src/tests/non262/regress/regress-314401.js | 40 + js/src/tests/non262/regress/regress-315990.js | 40 + js/src/tests/non262/regress/regress-317476.js | 31 + js/src/tests/non262/regress/regress-317714-01.js | 19 + js/src/tests/non262/regress/regress-317714-02.js | 20 + js/src/tests/non262/regress/regress-319384.js | 28 + js/src/tests/non262/regress/regress-319391.js | 39 + js/src/tests/non262/regress/regress-320032.js | 27 + js/src/tests/non262/regress/regress-320172.js | 24 + js/src/tests/non262/regress/regress-321757.js | 109 + js/src/tests/non262/regress/regress-321874.js | 207 + js/src/tests/non262/regress/regress-321971.js | 23 + js/src/tests/non262/regress/regress-325925.js | 19 + js/src/tests/non262/regress/regress-326467.js | 17 + js/src/tests/non262/regress/regress-328012.js | 29 + js/src/tests/non262/regress/regress-328664.js | 31 + js/src/tests/non262/regress/regress-329383.js | 83 + js/src/tests/non262/regress/regress-329530.js | 41 + js/src/tests/non262/regress/regress-330352.js | 35 + js/src/tests/non262/regress/regress-330951.js | 17 + js/src/tests/non262/regress/regress-334807-01.js | 24 + js/src/tests/non262/regress/regress-334807-02.js | 28 + js/src/tests/non262/regress/regress-334807-03.js | 24 + js/src/tests/non262/regress/regress-334807-04.js | 28 + js/src/tests/non262/regress/regress-334807-05.js | 33 + js/src/tests/non262/regress/regress-334807-06.js | 37 + js/src/tests/non262/regress/regress-336100.js | 24 + js/src/tests/non262/regress/regress-338307.js | 29 + js/src/tests/non262/regress/regress-340369.js | 23 + js/src/tests/non262/regress/regress-341360.js | 46 + js/src/tests/non262/regress/regress-343713.js | 21 + js/src/tests/non262/regress/regress-343966.js | 29 + js/src/tests/non262/regress/regress-344711-n.js | 31 + js/src/tests/non262/regress/regress-344804.js | 29 + js/src/tests/non262/regress/regress-344959.js | 33 + js/src/tests/non262/regress/regress-346237.js | 25 + js/src/tests/non262/regress/regress-346801.js | 73 + js/src/tests/non262/regress/regress-349482-01.js | 26 + js/src/tests/non262/regress/regress-349482-02.js | 26 + js/src/tests/non262/regress/regress-349592.js | 25 + js/src/tests/non262/regress/regress-350253.js | 31 + js/src/tests/non262/regress/regress-350268.js | 71 + js/src/tests/non262/regress/regress-350312.js | 77 + js/src/tests/non262/regress/regress-350415.js | 31 + js/src/tests/non262/regress/regress-350529.js | 30 + js/src/tests/non262/regress/regress-351116.js | 27 + js/src/tests/non262/regress/regress-351515.js | 33 + js/src/tests/non262/regress/regress-351795.js | 32 + js/src/tests/non262/regress/regress-352208.js | 42 + js/src/tests/non262/regress/regress-352604.js | 26 + js/src/tests/non262/regress/regress-352640-01.js | 30 + js/src/tests/non262/regress/regress-352640-02.js | 30 + js/src/tests/non262/regress/regress-352640-04.js | 30 + js/src/tests/non262/regress/regress-353078.js | 29 + js/src/tests/non262/regress/regress-353079.js | 26 + js/src/tests/non262/regress/regress-355023.js | 28 + js/src/tests/non262/regress/regress-355556.js | 32 + js/src/tests/non262/regress/regress-355569.js | 128 + js/src/tests/non262/regress/regress-355829-01.js | 25 + js/src/tests/non262/regress/regress-355829-02.js | 38 + js/src/tests/non262/regress/regress-355829-03.js | 26 + js/src/tests/non262/regress/regress-355832-01.js | 27 + js/src/tests/non262/regress/regress-355832-02.js | 27 + js/src/tests/non262/regress/regress-356250.js | 38 + js/src/tests/non262/regress/regress-356693.js | 33 + js/src/tests/non262/regress/regress-360969-01.js | 39 + js/src/tests/non262/regress/regress-360969-02.js | 32 + js/src/tests/non262/regress/regress-360969-03.js | 39 + js/src/tests/non262/regress/regress-360969-04.js | 32 + js/src/tests/non262/regress/regress-360969-05.js | 41 + js/src/tests/non262/regress/regress-360969-06.js | 33 + js/src/tests/non262/regress/regress-363040-01.js | 92 + js/src/tests/non262/regress/regress-363040-02.js | 64 + js/src/tests/non262/regress/regress-3649-n.js | 32 + js/src/tests/non262/regress/regress-366122.js | 43 + js/src/tests/non262/regress/regress-366468.js | 31 + js/src/tests/non262/regress/regress-366601.js | 35 + js/src/tests/non262/regress/regress-367561-01.js | 34 + js/src/tests/non262/regress/regress-367561-03.js | 33 + js/src/tests/non262/regress/regress-369666-01.js | 56 + js/src/tests/non262/regress/regress-369666-02.js | 60 + js/src/tests/non262/regress/regress-372364.js | 44 + js/src/tests/non262/regress/regress-373827-01.js | 25 + js/src/tests/non262/regress/regress-373827-02.js | 31 + js/src/tests/non262/regress/regress-373843.js | 13 + js/src/tests/non262/regress/regress-379245.js | 36 + js/src/tests/non262/regress/regress-379442.js | 25 + js/src/tests/non262/regress/regress-379483.js | 25 + js/src/tests/non262/regress/regress-383674.js | 52 + js/src/tests/non262/regress/regress-383682.js | 33 + js/src/tests/non262/regress/regress-383902.js | 41 + js/src/tests/non262/regress/regress-385393-04.js | 30 + js/src/tests/non262/regress/regress-387951-01.js | 25 + js/src/tests/non262/regress/regress-387951-02.js | 25 + js/src/tests/non262/regress/regress-387951-03.js | 25 + js/src/tests/non262/regress/regress-39309.js | 73 + js/src/tests/non262/regress/regress-396684.js | 45 + js/src/tests/non262/regress/regress-398085-01.js | 742 + js/src/tests/non262/regress/regress-398085-02.js | 725 + js/src/tests/non262/regress/regress-398609.js | 36 + js/src/tests/non262/regress/regress-404734.js | 28 + js/src/tests/non262/regress/regress-404755.js | 47 + js/src/tests/non262/regress/regress-406769.js | 152 + js/src/tests/non262/regress/regress-407024.js | 20 + js/src/tests/non262/regress/regress-407727-01.js | 17 + js/src/tests/non262/regress/regress-407727-02.js | 19 + js/src/tests/non262/regress/regress-410649.js | 39 + js/src/tests/non262/regress/regress-410852.js | 34 + js/src/tests/non262/regress/regress-414553.js | 27 + js/src/tests/non262/regress/regress-416737-01.js | 25 + js/src/tests/non262/regress/regress-416737-02.js | 30 + js/src/tests/non262/regress/regress-417893.js | 35 + js/src/tests/non262/regress/regress-418540.js | 51 + js/src/tests/non262/regress/regress-418641.js | 80 + js/src/tests/non262/regress/regress-419018.js | 44 + js/src/tests/non262/regress/regress-419152.js | 54 + js/src/tests/non262/regress/regress-419803.js | 25 + js/src/tests/non262/regress/regress-420087.js | 28 + js/src/tests/non262/regress/regress-420610.js | 17 + js/src/tests/non262/regress/regress-420919.js | 33 + js/src/tests/non262/regress/regress-422348.js | 35 + js/src/tests/non262/regress/regress-424311.js | 25 + js/src/tests/non262/regress/regress-425360.js | 32 + js/src/tests/non262/regress/regress-426827.js | 31 + js/src/tests/non262/regress/regress-427798.js | 55 + js/src/tests/non262/regress/regress-428366.js | 21 + js/src/tests/non262/regress/regress-433279-01.js | 25 + js/src/tests/non262/regress/regress-433279-02.js | 30 + js/src/tests/non262/regress/regress-433279-03.js | 30 + js/src/tests/non262/regress/regress-438415-01.js | 24 + js/src/tests/non262/regress/regress-438415-02.js | 28 + js/src/tests/non262/regress/regress-440926.js | 28 + js/src/tests/non262/regress/regress-441477-01.js | 39 + js/src/tests/non262/regress/regress-442333-01.js | 34 + js/src/tests/non262/regress/regress-449627.js | 114 + js/src/tests/non262/regress/regress-449666.js | 62 + js/src/tests/non262/regress/regress-450369.js | 307 + js/src/tests/non262/regress/regress-450833.js | 42 + js/src/tests/non262/regress/regress-451322.js | 34 + js/src/tests/non262/regress/regress-451884.js | 31 + js/src/tests/non262/regress/regress-451946.js | 29 + js/src/tests/non262/regress/regress-452008.js | 148 + js/src/tests/non262/regress/regress-452170.js | 26 + js/src/tests/non262/regress/regress-452189.js | 23 + js/src/tests/non262/regress/regress-452333.js | 26 + js/src/tests/non262/regress/regress-452336.js | 26 + js/src/tests/non262/regress/regress-452346.js | 25 + js/src/tests/non262/regress/regress-452491.js | 26 + js/src/tests/non262/regress/regress-452495.js | 19 + js/src/tests/non262/regress/regress-452498-006.js | 42 + js/src/tests/non262/regress/regress-452498-027.js | 35 + js/src/tests/non262/regress/regress-452498-030.js | 28 + js/src/tests/non262/regress/regress-452498-040.js | 34 + js/src/tests/non262/regress/regress-452498-050.js | 40 + js/src/tests/non262/regress/regress-452498-051.js | 45 + .../tests/non262/regress/regress-452498-052-a.js | 39 + js/src/tests/non262/regress/regress-452498-053.js | 77 + js/src/tests/non262/regress/regress-452498-058.js | 28 + js/src/tests/non262/regress/regress-452498-062.js | 41 + js/src/tests/non262/regress/regress-452498-063.js | 32 + js/src/tests/non262/regress/regress-452498-071.js | 28 + js/src/tests/non262/regress/regress-452498-072.js | 28 + js/src/tests/non262/regress/regress-452498-073.js | 35 + js/src/tests/non262/regress/regress-452498-074.js | 31 + js/src/tests/non262/regress/regress-452498-075.js | 29 + js/src/tests/non262/regress/regress-452498-076.js | 28 + js/src/tests/non262/regress/regress-452498-079.js | 31 + js/src/tests/non262/regress/regress-452498-082.js | 77 + js/src/tests/non262/regress/regress-452498-092.js | 37 + js/src/tests/non262/regress/regress-452498-102.js | 66 + js/src/tests/non262/regress/regress-452498-104.js | 28 + js/src/tests/non262/regress/regress-452498-111.js | 31 + js/src/tests/non262/regress/regress-452498-112.js | 36 + .../tests/non262/regress/regress-452498-114-a.js | 40 + js/src/tests/non262/regress/regress-452498-114.js | 47 + js/src/tests/non262/regress/regress-452498-116.js | 30 + js/src/tests/non262/regress/regress-452498-117.js | 78 + js/src/tests/non262/regress/regress-452498-118.js | 30 + js/src/tests/non262/regress/regress-452498-121.js | 30 + js/src/tests/non262/regress/regress-452498-123.js | 56 + js/src/tests/non262/regress/regress-452498-129.js | 47 + js/src/tests/non262/regress/regress-452498-131.js | 46 + js/src/tests/non262/regress/regress-452498-135.js | 43 + js/src/tests/non262/regress/regress-452498-155.js | 31 + js/src/tests/non262/regress/regress-452498-160.js | 26 + .../tests/non262/regress/regress-452498-168-1.js | 30 + .../tests/non262/regress/regress-452498-168-2.js | 29 + js/src/tests/non262/regress/regress-452498-176.js | 28 + js/src/tests/non262/regress/regress-452498-181.js | 28 + js/src/tests/non262/regress/regress-452498-185.js | 34 + js/src/tests/non262/regress/regress-452498-187.js | 33 + js/src/tests/non262/regress/regress-452498-191.js | 44 + js/src/tests/non262/regress/regress-452498-192.js | 27 + js/src/tests/non262/regress/regress-452573-01.js | 26 + js/src/tests/non262/regress/regress-452573-02.js | 26 + js/src/tests/non262/regress/regress-452703.js | 19 + js/src/tests/non262/regress/regress-452713.js | 26 + js/src/tests/non262/regress/regress-452724-01.js | 26 + js/src/tests/non262/regress/regress-452724-02.js | 26 + js/src/tests/non262/regress/regress-452742-01.js | 48 + js/src/tests/non262/regress/regress-452742-02.js | 53 + js/src/tests/non262/regress/regress-452853.js | 26 + js/src/tests/non262/regress/regress-452884-01.js | 26 + js/src/tests/non262/regress/regress-452884-02.js | 26 + js/src/tests/non262/regress/regress-452960.js | 28 + js/src/tests/non262/regress/regress-453024.js | 35 + js/src/tests/non262/regress/regress-453049.js | 26 + js/src/tests/non262/regress/regress-453051.js | 26 + js/src/tests/non262/regress/regress-453173.js | 28 + js/src/tests/non262/regress/regress-453397.js | 43 + js/src/tests/non262/regress/regress-453701.js | 26 + js/src/tests/non262/regress/regress-453747.js | 34 + js/src/tests/non262/regress/regress-454682.js | 30 + js/src/tests/non262/regress/regress-454981.js | 31 + js/src/tests/non262/regress/regress-455605.js | 27 + js/src/tests/non262/regress/regress-455748.js | 27 + js/src/tests/non262/regress/regress-455758-01.js | 27 + js/src/tests/non262/regress/regress-455758-02.js | 27 + js/src/tests/non262/regress/regress-455775.js | 31 + js/src/tests/non262/regress/regress-455981-01.js | 33 + js/src/tests/non262/regress/regress-455981-02.js | 33 + js/src/tests/non262/regress/regress-456470.js | 35 + js/src/tests/non262/regress/regress-456477-01.js | 27 + js/src/tests/non262/regress/regress-456477-02.js | 27 + js/src/tests/non262/regress/regress-456494.js | 36 + js/src/tests/non262/regress/regress-456540-01.js | 27 + js/src/tests/non262/regress/regress-456540-02.js | 27 + js/src/tests/non262/regress/regress-457065-01.js | 29 + js/src/tests/non262/regress/regress-457065-02.js | 27 + js/src/tests/non262/regress/regress-457065-03.js | 29 + js/src/tests/non262/regress/regress-457456.js | 27 + js/src/tests/non262/regress/regress-457778.js | 27 + js/src/tests/non262/regress/regress-458076.js | 27 + js/src/tests/non262/regress/regress-458851.js | 30 + js/src/tests/non262/regress/regress-459085.js | 31 + js/src/tests/non262/regress/regress-459185.js | 31 + js/src/tests/non262/regress/regress-459186.js | 31 + js/src/tests/non262/regress/regress-459389.js | 119 + js/src/tests/non262/regress/regress-459628.js | 31 + js/src/tests/non262/regress/regress-459990.js | 30 + js/src/tests/non262/regress/regress-460024.js | 36 + js/src/tests/non262/regress/regress-460117.js | 42 + js/src/tests/non262/regress/regress-460886-01.js | 25 + js/src/tests/non262/regress/regress-460886-02.js | 25 + js/src/tests/non262/regress/regress-461307.js | 28 + js/src/tests/non262/regress/regress-461723.js | 27 + js/src/tests/non262/regress/regress-462071.js | 27 + js/src/tests/non262/regress/regress-462282.js | 27 + js/src/tests/non262/regress/regress-462292.js | 31 + js/src/tests/non262/regress/regress-462388.js | 27 + js/src/tests/non262/regress/regress-462407.js | 19 + js/src/tests/non262/regress/regress-462879.js | 31 + js/src/tests/non262/regress/regress-462989.js | 31 + js/src/tests/non262/regress/regress-463259.js | 27 + js/src/tests/non262/regress/regress-463782.js | 66 + js/src/tests/non262/regress/regress-464096.js | 29 + js/src/tests/non262/regress/regress-464334.js | 33 + js/src/tests/non262/regress/regress-464403.js | 29 + js/src/tests/non262/regress/regress-464418.js | 43 + js/src/tests/non262/regress/regress-464862.js | 123 + js/src/tests/non262/regress/regress-464978.js | 27 + js/src/tests/non262/regress/regress-465013.js | 36 + js/src/tests/non262/regress/regress-465132.js | 39 + js/src/tests/non262/regress/regress-465133.js | 30 + js/src/tests/non262/regress/regress-465135.js | 30 + js/src/tests/non262/regress/regress-465136.js | 30 + js/src/tests/non262/regress/regress-465137.js | 30 + js/src/tests/non262/regress/regress-465220.js | 40 + js/src/tests/non262/regress/regress-465234.js | 30 + js/src/tests/non262/regress/regress-465236.js | 25 + js/src/tests/non262/regress/regress-465239.js | 30 + js/src/tests/non262/regress/regress-465241.js | 30 + js/src/tests/non262/regress/regress-465249.js | 27 + js/src/tests/non262/regress/regress-465261.js | 31 + js/src/tests/non262/regress/regress-465262.js | 29 + js/src/tests/non262/regress/regress-465272.js | 29 + js/src/tests/non262/regress/regress-465308.js | 28 + js/src/tests/non262/regress/regress-465347.js | 49 + js/src/tests/non262/regress/regress-465366.js | 36 + js/src/tests/non262/regress/regress-465424.js | 27 + js/src/tests/non262/regress/regress-465454.js | 28 + js/src/tests/non262/regress/regress-465460-01.js | 29 + js/src/tests/non262/regress/regress-465460-02.js | 27 + js/src/tests/non262/regress/regress-465460-03.js | 26 + js/src/tests/non262/regress/regress-465460-04.js | 27 + js/src/tests/non262/regress/regress-465460-05.js | 27 + js/src/tests/non262/regress/regress-465460-06.js | 27 + js/src/tests/non262/regress/regress-465460-07.js | 35 + js/src/tests/non262/regress/regress-465460-08.js | 27 + js/src/tests/non262/regress/regress-465460-10.js | 27 + js/src/tests/non262/regress/regress-465460-11.js | 27 + js/src/tests/non262/regress/regress-465460-12.js | 27 + js/src/tests/non262/regress/regress-465483.js | 27 + js/src/tests/non262/regress/regress-465484.js | 25 + js/src/tests/non262/regress/regress-465567-01.js | 29 + js/src/tests/non262/regress/regress-465567-02.js | 25 + js/src/tests/non262/regress/regress-465686.js | 32 + js/src/tests/non262/regress/regress-465688.js | 25 + js/src/tests/non262/regress/regress-466128.js | 28 + js/src/tests/non262/regress/regress-466262.js | 31 + js/src/tests/non262/regress/regress-466747.js | 48 + js/src/tests/non262/regress/regress-466787.js | 30 + js/src/tests/non262/regress/regress-466905-01.js | 27 + js/src/tests/non262/regress/regress-466905-02.js | 26 + js/src/tests/non262/regress/regress-467495-01.js | 25 + js/src/tests/non262/regress/regress-467495-02.js | 31 + js/src/tests/non262/regress/regress-467495-03.js | 44 + js/src/tests/non262/regress/regress-467495-04.js | 39 + js/src/tests/non262/regress/regress-467495-05.js | 28 + js/src/tests/non262/regress/regress-467495-06.js | 41 + js/src/tests/non262/regress/regress-468711.js | 27 + js/src/tests/non262/regress/regress-469044.js | 68 + js/src/tests/non262/regress/regress-469239-01.js | 33 + js/src/tests/non262/regress/regress-469239-02.js | 33 + js/src/tests/non262/regress/regress-469547.js | 31 + js/src/tests/non262/regress/regress-469625-02.js | 32 + js/src/tests/non262/regress/regress-469625-03.js | 38 + js/src/tests/non262/regress/regress-469758.js | 14 + js/src/tests/non262/regress/regress-469937.js | 27 + js/src/tests/non262/regress/regress-470061.js | 40 + js/src/tests/non262/regress/regress-470187-01.js | 25 + js/src/tests/non262/regress/regress-470187-02.js | 24 + js/src/tests/non262/regress/regress-470223.js | 35 + js/src/tests/non262/regress/regress-470388-01.js | 25 + js/src/tests/non262/regress/regress-470758-01.js | 27 + js/src/tests/non262/regress/regress-470758-02.js | 29 + js/src/tests/non262/regress/regress-471660.js | 34 + js/src/tests/non262/regress/regress-472533.js | 25 + js/src/tests/non262/regress/regress-474769.js | 32 + js/src/tests/non262/regress/regress-474771-01.js | 38 + js/src/tests/non262/regress/regress-474771.js | 42 + js/src/tests/non262/regress/regress-474935.js | 37 + js/src/tests/non262/regress/regress-475469.js | 30 + js/src/tests/non262/regress/regress-475645-01.js | 44 + js/src/tests/non262/regress/regress-475645-02.js | 51 + js/src/tests/non262/regress/regress-476049.js | 43 + js/src/tests/non262/regress/regress-476192.js | 35 + js/src/tests/non262/regress/regress-476655.js | 36 + js/src/tests/non262/regress/regress-477053.js | 25 + js/src/tests/non262/regress/regress-477234.js | 40 + js/src/tests/non262/regress/regress-477733.js | 39 + js/src/tests/non262/regress/regress-477758.js | 46 + js/src/tests/non262/regress/regress-478205.js | 27 + js/src/tests/non262/regress/regress-478314.js | 27 + js/src/tests/non262/regress/regress-479353-01.js | 23 + js/src/tests/non262/regress/regress-479353.js | 25 + js/src/tests/non262/regress/regress-479430-01.js | 41 + js/src/tests/non262/regress/regress-479430-02.js | 43 + js/src/tests/non262/regress/regress-479430-03.js | 46 + js/src/tests/non262/regress/regress-479430-04.js | 42 + js/src/tests/non262/regress/regress-479430-05.js | 41 + js/src/tests/non262/regress/regress-479740.js | 36 + js/src/tests/non262/regress/regress-480147.js | 29 + js/src/tests/non262/regress/regress-480244.js | 48 + js/src/tests/non262/regress/regress-481436.js | 38 + js/src/tests/non262/regress/regress-481800.js | 27 + js/src/tests/non262/regress/regress-482421.js | 26 + js/src/tests/non262/regress/regress-482783.js | 29 + js/src/tests/non262/regress/regress-483103.js | 30 + js/src/tests/non262/regress/regress-483749.js | 25 + js/src/tests/non262/regress/regress-495773.js | 39 + js/src/tests/non262/regress/regress-495907.js | 32 + js/src/tests/non262/regress/regress-496922.js | 36 + js/src/tests/non262/regress/regress-499524.js | 50 + js/src/tests/non262/regress/regress-500528.js | 22 + js/src/tests/non262/regress/regress-501124.js | 40 + js/src/tests/non262/regress/regress-503860.js | 24 + js/src/tests/non262/regress/regress-504078.js | 48 + js/src/tests/non262/regress/regress-507053.js | 44 + js/src/tests/non262/regress/regress-507295.js | 39 + js/src/tests/non262/regress/regress-509354.js | 41 + js/src/tests/non262/regress/regress-511859.js | 147 + js/src/tests/non262/regress/regress-522123.js | 35 + js/src/tests/non262/regress/regress-524743.js | 20 + js/src/tests/non262/regress/regress-530879.js | 9 + js/src/tests/non262/regress/regress-532491.js | 34 + js/src/tests/non262/regress/regress-541255-3.js | 13 + js/src/tests/non262/regress/regress-541455.js | 12 + js/src/tests/non262/regress/regress-551763-0.js | 27 + js/src/tests/non262/regress/regress-551763-1.js | 4 + js/src/tests/non262/regress/regress-551763-2.js | 3 + js/src/tests/non262/regress/regress-552432.js | 16 + js/src/tests/non262/regress/regress-553778.js | 16 + js/src/tests/non262/regress/regress-554955-1.js | 33 + js/src/tests/non262/regress/regress-554955-2.js | 29 + js/src/tests/non262/regress/regress-554955-3.js | 32 + js/src/tests/non262/regress/regress-554955-4.js | 37 + js/src/tests/non262/regress/regress-554955-5.js | 30 + js/src/tests/non262/regress/regress-554955-6.js | 50 + js/src/tests/non262/regress/regress-555246-0.js | 14 + js/src/tests/non262/regress/regress-555246-1.js | 18 + js/src/tests/non262/regress/regress-559402-1.js | 14 + js/src/tests/non262/regress/regress-559402-2.js | 8 + js/src/tests/non262/regress/regress-559438.js | 10 + js/src/tests/non262/regress/regress-560998-1.js | 10 + js/src/tests/non262/regress/regress-560998-2.js | 10 + js/src/tests/non262/regress/regress-561031.js | 1830 + js/src/tests/non262/regress/regress-563210.js | 28 + js/src/tests/non262/regress/regress-563221.js | 8 + js/src/tests/non262/regress/regress-566549.js | 20 + js/src/tests/non262/regress/regress-567152.js | 12 + js/src/tests/non262/regress/regress-569306.js | 10 + js/src/tests/non262/regress/regress-57043.js | 76 + js/src/tests/non262/regress/regress-571014.js | 32 + js/src/tests/non262/regress/regress-573875.js | 21 + js/src/tests/non262/regress/regress-577648-1.js | 87 + js/src/tests/non262/regress/regress-577648-2.js | 12 + js/src/tests/non262/regress/regress-580544.js | 27 + js/src/tests/non262/regress/regress-58116.js | 31 + js/src/tests/non262/regress/regress-583429.js | 7 + js/src/tests/non262/regress/regress-584355.js | 7 + js/src/tests/non262/regress/regress-585257.js | 7 + js/src/tests/non262/regress/regress-586482-1.js | 25 + js/src/tests/non262/regress/regress-586482-2.js | 22 + js/src/tests/non262/regress/regress-586482-3.js | 27 + js/src/tests/non262/regress/regress-586482-4.js | 25 + js/src/tests/non262/regress/regress-586482-5.js | 18 + js/src/tests/non262/regress/regress-588339.js | 5 + js/src/tests/non262/regress/regress-591846.js | 64 + js/src/tests/non262/regress/regress-591897.js | 13 + js/src/tests/non262/regress/regress-592202-3.js | 28 + js/src/tests/non262/regress/regress-592202-4.js | 31 + js/src/tests/non262/regress/regress-592556-c35.js | 20 + js/src/tests/non262/regress/regress-593256.js | 21 + js/src/tests/non262/regress/regress-595230-2.js | 10 + js/src/tests/non262/regress/regress-595365-1.js | 31 + js/src/tests/non262/regress/regress-596103.js | 13 + js/src/tests/non262/regress/regress-596805-1.js | 14 + js/src/tests/non262/regress/regress-596805-2.js | 27 + js/src/tests/non262/regress/regress-597945-1.js | 24 + js/src/tests/non262/regress/regress-597945-2.js | 13 + js/src/tests/non262/regress/regress-598176.js | 27 + js/src/tests/non262/regress/regress-600067.js | 16 + js/src/tests/non262/regress/regress-601399.js | 25 + js/src/tests/non262/regress/regress-602621.js | 15 + js/src/tests/non262/regress/regress-607799.js | 2 + js/src/tests/non262/regress/regress-607863.js | 14 + js/src/tests/non262/regress/regress-609617.js | 85 + js/src/tests/non262/regress/regress-610026.js | 49 + js/src/tests/non262/regress/regress-614714.js | 12 + js/src/tests/non262/regress/regress-617405-1.js | 11 + js/src/tests/non262/regress/regress-617405-2.js | 17 + js/src/tests/non262/regress/regress-618572.js | 34 + js/src/tests/non262/regress/regress-619003-1.js | 20 + js/src/tests/non262/regress/regress-619003-2.js | 9 + js/src/tests/non262/regress/regress-620376-1.js | 24 + js/src/tests/non262/regress/regress-624547.js | 16 + js/src/tests/non262/regress/regress-624968.js | 9 + js/src/tests/non262/regress/regress-626436.js | 7 + js/src/tests/non262/regress/regress-633741.js | 18 + js/src/tests/non262/regress/regress-634210-1.js | 11 + js/src/tests/non262/regress/regress-634210-2.js | 13 + js/src/tests/non262/regress/regress-634210-3.js | 13 + js/src/tests/non262/regress/regress-634210-4.js | 20 + js/src/tests/non262/regress/regress-636364.js | 29 + js/src/tests/non262/regress/regress-640075.js | 15 + js/src/tests/non262/regress/regress-642247.js | 13 + js/src/tests/non262/regress/regress-643222.js | 12 + js/src/tests/non262/regress/regress-646820-1.js | 9 + js/src/tests/non262/regress/regress-646820-2.js | 11 + js/src/tests/non262/regress/regress-646820-3.js | 9 + js/src/tests/non262/regress/regress-665355.js | 19 + js/src/tests/non262/regress/regress-672892.js | 8 + js/src/tests/non262/regress/regress-672893.js | 18 + js/src/tests/non262/regress/regress-68498-001.js | 42 + js/src/tests/non262/regress/regress-68498-002.js | 64 + js/src/tests/non262/regress/regress-68498-003.js | 68 + js/src/tests/non262/regress/regress-68498-004.js | 96 + js/src/tests/non262/regress/regress-694306.js | 21 + js/src/tests/non262/regress/regress-69607.js | 42 + js/src/tests/non262/regress/regress-698028-1.js | 24 + js/src/tests/non262/regress/regress-698028-2.js | 29 + js/src/tests/non262/regress/regress-698028-3.js | 15 + js/src/tests/non262/regress/regress-699682.js | 29 + js/src/tests/non262/regress/regress-71107.js | 43 + js/src/tests/non262/regress/regress-76054.js | 123 + js/src/tests/non262/regress/regress-80981.js | 3111 + js/src/tests/non262/regress/regress-810525.js | 25 + js/src/tests/non262/regress/regress-82306.js | 45 + js/src/tests/non262/regress/regress-89443.js | 2119 + js/src/tests/non262/regress/regress-89474.js | 47 + js/src/tests/non262/regress/regress-90445.js | 295 + js/src/tests/non262/regress/regress-96128-n.js | 48 + js/src/tests/non262/regress/regress-96526-001.js | 504 + js/src/tests/non262/regress/regress-96526-002.js | 30 + js/src/tests/non262/regress/regress-96526-003.js | 4405 ++ js/src/tests/non262/regress/regress-98901.js | 3892 ++ js/src/tests/non262/regress/shell.js | 0 js/src/tests/non262/shell.js | 339 + .../arrow-function-at-end-of-for-statement-head.js | 64 + .../arrow-function-in-for-statement-head.js | 33 + js/src/tests/non262/statements/browser.js | 0 .../statements/for-in-with-assignment-semantics.js | 46 + .../statements/for-in-with-assignment-syntax.js | 66 + .../non262/statements/for-in-with-assignments.js | 87 + .../non262/statements/for-in-with-declaration.js | 31 + .../for-in-with-destructuring-assignments.js | 130 + .../for-in-with-gc-and-unvisited-deletion.js | 76 + .../for-in-with-gc-during-iterator-init.js | 30 + .../for-inof-coverinitname-destr-assign.js | 55 + js/src/tests/non262/statements/for-inof-finally.js | 78 + .../statements/for-inof-loop-const-declaration.js | 94 + ...e-iteration-expression-contains-index-string.js | 43 + .../for-loop-declaration-contains-computed-name.js | 48 + .../for-loop-declaration-contains-initializer.js | 50 + .../statements/for-of-async-of-starting-lhs.js | 115 + .../statements/for-of-iterator-close-throw.js | 35 + .../non262/statements/for-of-iterator-close.js | 102 + .../non262/statements/for-of-iterator-primitive.js | 28 + .../statements/for-of-var-with-initializer.js | 32 + .../tests/non262/statements/if-constant-folding.js | 35 + .../property-reference-self-assignment.js | 38 + js/src/tests/non262/statements/regress-131348.js | 147 + js/src/tests/non262/statements/regress-157509.js | 74 + js/src/tests/non262/statements/regress-194364.js | 115 + js/src/tests/non262/statements/regress-226517.js | 75 + js/src/tests/non262/statements/regress-302439.js | 1335 + js/src/tests/non262/statements/regress-324650.js | 5427 ++ js/src/tests/non262/statements/regress-444979.js | 40 + js/src/tests/non262/statements/regress-642975.js | 30 + .../tests/non262/statements/regress-74474-001.js | 102 + .../tests/non262/statements/regress-74474-002.js | 9060 +++ .../tests/non262/statements/regress-74474-003.js | 9062 +++ .../tests/non262/statements/regress-83532-001.js | 34 + .../tests/non262/statements/regress-83532-002.js | 37 + js/src/tests/non262/statements/shell.js | 0 .../non262/statements/trailing_comma_parameters.js | 92 + js/src/tests/non262/statements/try-completion.js | 482 + js/src/tests/non262/strict/10.4.2.js | 55 + js/src/tests/non262/strict/10.4.3.js | 58 + js/src/tests/non262/strict/10.6.js | 55 + js/src/tests/non262/strict/11.1.5.js | 171 + js/src/tests/non262/strict/11.13.1.js | 29 + js/src/tests/non262/strict/11.13.2.js | 29 + js/src/tests/non262/strict/11.3.1.js | 29 + js/src/tests/non262/strict/11.3.2.js | 29 + js/src/tests/non262/strict/11.4.1.js | 45 + js/src/tests/non262/strict/11.4.4.js | 29 + js/src/tests/non262/strict/11.4.5.js | 29 + js/src/tests/non262/strict/12.10.1.js | 30 + js/src/tests/non262/strict/12.14.1.js | 37 + js/src/tests/non262/strict/12.2.1-01.js | 75 + js/src/tests/non262/strict/12.2.1.js | 25 + js/src/tests/non262/strict/13.1.js | 345 + js/src/tests/non262/strict/15.10.7.js | 15 + js/src/tests/non262/strict/15.3.4.5.js | 26 + js/src/tests/non262/strict/15.3.5.1.js | 16 + js/src/tests/non262/strict/15.3.5.2.js | 16 + js/src/tests/non262/strict/15.4.4.11.js | 32 + js/src/tests/non262/strict/15.4.4.12.js | 50 + js/src/tests/non262/strict/15.4.4.13.js | 50 + js/src/tests/non262/strict/15.4.4.6.js | 28 + js/src/tests/non262/strict/15.4.4.8.js | 50 + js/src/tests/non262/strict/15.4.4.9.js | 50 + js/src/tests/non262/strict/15.4.5.1.js | 84 + js/src/tests/non262/strict/15.5.5.1.js | 26 + js/src/tests/non262/strict/15.5.5.2.js | 15 + js/src/tests/non262/strict/8.12.5.js | 82 + js/src/tests/non262/strict/8.12.7-2.js | 21 + js/src/tests/non262/strict/8.12.7.js | 32 + js/src/tests/non262/strict/8.7.2-01.js | 17 + js/src/tests/non262/strict/8.7.2.js | 56 + js/src/tests/non262/strict/B.1.1.js | 31 + js/src/tests/non262/strict/B.1.2.js | 38 + .../tests/non262/strict/assign-to-callee-name.js | 42 + js/src/tests/non262/strict/browser.js | 0 .../strict/deprecated-octal-noctal-tokens.js | 53 + .../tests/non262/strict/directive-prologue-01.js | 78 + .../non262/strict/eval-variable-environment.js | 67 + js/src/tests/non262/strict/primitive-assignment.js | 23 + .../tests/non262/strict/primitive-this-getter.js | 56 + .../non262/strict/primitive-this-no-writeback.js | 20 + .../rebind-eval-should-fail-in-strict-mode.js | 39 + js/src/tests/non262/strict/regress-532041.js | 17 + js/src/tests/non262/strict/regress-532254.js | 13 + js/src/tests/non262/strict/regress-599159.js | 33 + js/src/tests/non262/strict/shell.js | 65 + .../non262/strict/strict-function-statements.js | 94 + .../non262/strict/strict-this-is-not-truthy.js | 12 + .../this-for-function-expression-recursion.js | 44 + js/src/tests/non262/strict/unbrand-this.js | 45 + js/src/tests/non262/syntax/browser.js | 0 js/src/tests/non262/syntax/bug1863308.js | 35 + .../non262/syntax/column-numbers-in-long-lines.js | 403 + .../syntax/declaration-forbidden-in-label.js | 34 + .../non262/syntax/escaped-let-static-identifier.js | 57 + .../escaped-strict-reserved-words-and-yield.js | 105 + .../non262/syntax/identifier_vertical_tilde.js | 20 + .../identifiers-with-extended-unicode-escape.js | 208 + .../non262/syntax/keyword-unescaped-requirement.js | 68 + js/src/tests/non262/syntax/let-as-label.js | 35 + ...ining-escape-terminated-by-unicode-separator.js | 41 + ...ed-at-eof-in-unterminated-string-or-template.js | 88 + .../syntax/non-simple-with-strict-directive.js | 140 + .../tests/non262/syntax/omitted-catch-binding.js | 36 + js/src/tests/non262/syntax/shell.js | 0 .../syntax/statement-versus-statementlistitem.js | 148 + .../syntax/syntax-parsed-arrow-then-bigint.js | 40 + .../syntax/syntax-parsed-arrow-then-directive.js | 72 + ...syntax-parsed-arrow-then-sourcemap-directive.js | 63 + .../non262/syntax/unicode_other_id_continue.js | 45 + .../tests/non262/syntax/unicode_other_id_start.js | 48 + js/src/tests/non262/syntax/yield-as-identifier.js | 54 + js/src/tests/non262/template-strings/browser.js | 2 + js/src/tests/non262/template-strings/bug1559123.js | 15 + .../non262/template-strings/debugLineNumber.js | 50 + js/src/tests/non262/template-strings/lineNumber.js | 72 + js/src/tests/non262/template-strings/noSubst.js | 148 + js/src/tests/non262/template-strings/shell.js | 0 js/src/tests/non262/template-strings/tagTempl.js | 464 + js/src/tests/non262/template-strings/templLit.js | 118 + js/src/tests/non262/template.js | 25 + js/src/tests/non262/types/8.12.5-01.js | 110 + js/src/tests/non262/types/browser.js | 0 js/src/tests/non262/types/shell.js | 0 3575 files changed, 459826 insertions(+) create mode 100644 js/src/tests/non262/Array/11.1.4.js create mode 100644 js/src/tests/non262/Array/15.4.4.5-1.js create mode 100644 js/src/tests/non262/Array/15.4.4.5-2.js create mode 100644 js/src/tests/non262/Array/15.4.4.5-3.js create mode 100644 js/src/tests/non262/Array/array-001.js create mode 100644 js/src/tests/non262/Array/array-length-set-during-for-in.js create mode 100644 js/src/tests/non262/Array/array-length-set-on-nonarray.js create mode 100644 js/src/tests/non262/Array/at.js create mode 100644 js/src/tests/non262/Array/browser.js create mode 100644 js/src/tests/non262/Array/change-array-by-copy-cross-compartment-create.js create mode 100644 js/src/tests/non262/Array/change-array-by-copy-errors-from-correct-realm.js create mode 100644 js/src/tests/non262/Array/concat-proxy.js create mode 100644 js/src/tests/non262/Array/concat-spreadable-basic.js create mode 100644 js/src/tests/non262/Array/concat-spreadable-primitive.js create mode 100644 js/src/tests/non262/Array/fill.js create mode 100644 js/src/tests/non262/Array/filter.js create mode 100644 js/src/tests/non262/Array/findLast_findLastIndex.js create mode 100644 js/src/tests/non262/Array/find_findindex.js create mode 100644 js/src/tests/non262/Array/for_of_1.js create mode 100644 js/src/tests/non262/Array/for_of_2.js create mode 100644 js/src/tests/non262/Array/for_of_3.js create mode 100644 js/src/tests/non262/Array/for_of_4.js create mode 100644 js/src/tests/non262/Array/from-iterator-close.js create mode 100644 js/src/tests/non262/Array/from_async.js create mode 100644 js/src/tests/non262/Array/from_basics.js create mode 100644 js/src/tests/non262/Array/from_constructor.js create mode 100644 js/src/tests/non262/Array/from_errors.js create mode 100644 js/src/tests/non262/Array/from_iterable.js create mode 100644 js/src/tests/non262/Array/from_length_setter.js create mode 100644 js/src/tests/non262/Array/from_mapping.js create mode 100644 js/src/tests/non262/Array/from_primitive.js create mode 100644 js/src/tests/non262/Array/from_proxy.js create mode 100644 js/src/tests/non262/Array/from_realms.js create mode 100644 js/src/tests/non262/Array/from_string.js create mode 100644 js/src/tests/non262/Array/from_surfaces.js create mode 100644 js/src/tests/non262/Array/from_this.js create mode 100644 js/src/tests/non262/Array/frozen-dense-array.js create mode 100644 js/src/tests/non262/Array/frozen-dict-mode-length.js create mode 100644 js/src/tests/non262/Array/getter-name.js create mode 100644 js/src/tests/non262/Array/group-callback-evaluation.js create mode 100644 js/src/tests/non262/Array/group-propertkey-is-length.js create mode 100644 js/src/tests/non262/Array/group.js create mode 100644 js/src/tests/non262/Array/includes-trailing-holes.js create mode 100644 js/src/tests/non262/Array/includes.js create mode 100644 js/src/tests/non262/Array/index-with-null-character.js create mode 100644 js/src/tests/non262/Array/indexOf-never-returns-negative-zero.js create mode 100644 js/src/tests/non262/Array/indexOf-packed-array.js create mode 100644 js/src/tests/non262/Array/isArray.js create mode 100644 js/src/tests/non262/Array/iterator_edge_cases.js create mode 100644 js/src/tests/non262/Array/join-01.js create mode 100644 js/src/tests/non262/Array/join-no-has-trap.js create mode 100644 js/src/tests/non262/Array/lastIndexOf-never-returns-negative-zero.js create mode 100644 js/src/tests/non262/Array/length-01.js create mode 100644 js/src/tests/non262/Array/length-nonwritable-redefine-nop.js create mode 100644 js/src/tests/non262/Array/length-set-object.js create mode 100644 js/src/tests/non262/Array/length-truncate-nonconfigurable-sparse.js create mode 100644 js/src/tests/non262/Array/length-truncate-nonconfigurable.js create mode 100644 js/src/tests/non262/Array/length-truncate-with-indexed.js create mode 100644 js/src/tests/non262/Array/pop-empty-nonwritable.js create mode 100644 js/src/tests/non262/Array/pop-no-has-trap.js create mode 100644 js/src/tests/non262/Array/pop-nonarray-higher-elements.js create mode 100644 js/src/tests/non262/Array/redefine-length-accessor.js create mode 100644 js/src/tests/non262/Array/redefine-length-frozen-array.js create mode 100644 js/src/tests/non262/Array/redefine-length-frozen-dictionarymode-array.js create mode 100644 js/src/tests/non262/Array/redefine-nonwritable-length-custom-conversion-call-counts.js create mode 100644 js/src/tests/non262/Array/redefine-nonwritable-length-custom-conversion-throw.js create mode 100644 js/src/tests/non262/Array/redefine-nonwritable-length-nonnumeric.js create mode 100644 js/src/tests/non262/Array/regress-101488.js create mode 100644 js/src/tests/non262/Array/regress-107138.js create mode 100644 js/src/tests/non262/Array/regress-108440.js create mode 100644 js/src/tests/non262/Array/regress-130451.js create mode 100644 js/src/tests/non262/Array/regress-154338.js create mode 100644 js/src/tests/non262/Array/regress-157652.js create mode 100644 js/src/tests/non262/Array/regress-178722.js create mode 100644 js/src/tests/non262/Array/regress-255555.js create mode 100644 js/src/tests/non262/Array/regress-290592.js create mode 100644 js/src/tests/non262/Array/regress-299644.js create mode 100644 js/src/tests/non262/Array/regress-300858.js create mode 100644 js/src/tests/non262/Array/regress-304828.js create mode 100644 js/src/tests/non262/Array/regress-305002.js create mode 100644 js/src/tests/non262/Array/regress-310351.js create mode 100644 js/src/tests/non262/Array/regress-310425-01.js create mode 100644 js/src/tests/non262/Array/regress-310425-02.js create mode 100644 js/src/tests/non262/Array/regress-311515.js create mode 100644 js/src/tests/non262/Array/regress-315509-01.js create mode 100644 js/src/tests/non262/Array/regress-322135-01.js create mode 100644 js/src/tests/non262/Array/regress-330812.js create mode 100644 js/src/tests/non262/Array/regress-345961.js create mode 100644 js/src/tests/non262/Array/regress-348810.js create mode 100644 js/src/tests/non262/Array/regress-350256-01.js create mode 100644 js/src/tests/non262/Array/regress-350256-02.js create mode 100644 js/src/tests/non262/Array/regress-352742-01.js create mode 100644 js/src/tests/non262/Array/regress-352742-02.js create mode 100644 js/src/tests/non262/Array/regress-360681-01.js create mode 100644 js/src/tests/non262/Array/regress-360681-02.js create mode 100644 js/src/tests/non262/Array/regress-364104.js create mode 100644 js/src/tests/non262/Array/regress-386030.js create mode 100644 js/src/tests/non262/Array/regress-387501.js create mode 100644 js/src/tests/non262/Array/regress-390598.js create mode 100644 js/src/tests/non262/Array/regress-415451.js create mode 100644 js/src/tests/non262/Array/regress-421325.js create mode 100644 js/src/tests/non262/Array/regress-422286.js create mode 100644 js/src/tests/non262/Array/regress-424954.js create mode 100644 js/src/tests/non262/Array/regress-430717.js create mode 100644 js/src/tests/non262/Array/regress-451483.js create mode 100644 js/src/tests/non262/Array/regress-451906.js create mode 100644 js/src/tests/non262/Array/regress-456845.js create mode 100644 js/src/tests/non262/Array/regress-465980-01.js create mode 100644 js/src/tests/non262/Array/regress-465980-02.js create mode 100644 js/src/tests/non262/Array/regress-474529.js create mode 100644 js/src/tests/non262/Array/regress-488989.js create mode 100644 js/src/tests/non262/Array/regress-566651.js create mode 100644 js/src/tests/non262/Array/regress-599159.js create mode 100644 js/src/tests/non262/Array/regress-619970.js create mode 100644 js/src/tests/non262/Array/regress-94257.js create mode 100644 js/src/tests/non262/Array/reverse-order-of-low-high-accesses.js create mode 100644 js/src/tests/non262/Array/set-with-indexed-property-on-prototype-chain.js create mode 100644 js/src/tests/non262/Array/shell.js create mode 100644 js/src/tests/non262/Array/shift-no-has-trap.js create mode 100644 js/src/tests/non262/Array/shift_for_in.js create mode 100644 js/src/tests/non262/Array/slice-sparse-with-large-index.js create mode 100644 js/src/tests/non262/Array/sort-01.js create mode 100644 js/src/tests/non262/Array/sort-array-with-holes-and-undefined.js create mode 100644 js/src/tests/non262/Array/sort-delete-ascending-order.js create mode 100644 js/src/tests/non262/Array/sort-non-function.js create mode 100644 js/src/tests/non262/Array/sort-typedarray-with-own-length.js create mode 100644 js/src/tests/non262/Array/sort_basics.js create mode 100644 js/src/tests/non262/Array/sort_holes.js create mode 100644 js/src/tests/non262/Array/sort_native_string_nan.js create mode 100644 js/src/tests/non262/Array/sort_proxy.js create mode 100644 js/src/tests/non262/Array/sort_small.js create mode 100644 js/src/tests/non262/Array/species.js create mode 100644 js/src/tests/non262/Array/splice-return-array-elements-defined-not-set.js create mode 100644 js/src/tests/non262/Array/splice-species-changes-length.js create mode 100644 js/src/tests/non262/Array/splice-suppresses-unvisited-indexes.js create mode 100644 js/src/tests/non262/Array/to-length.js create mode 100644 js/src/tests/non262/Array/toLocaleString-01.js create mode 100644 js/src/tests/non262/Array/toLocaleString-nointl.js create mode 100644 js/src/tests/non262/Array/toLocaleString.js create mode 100644 js/src/tests/non262/Array/toSpliced-dense.js create mode 100644 js/src/tests/non262/Array/toSpliced.js create mode 100644 js/src/tests/non262/Array/toString-01.js create mode 100644 js/src/tests/non262/Array/unscopables.js create mode 100644 js/src/tests/non262/Array/unshift-01.js create mode 100644 js/src/tests/non262/Array/unshift-with-enumeration.js create mode 100644 js/src/tests/non262/Array/values.js create mode 100644 js/src/tests/non262/Array/with-dense.js create mode 100644 js/src/tests/non262/Array/with.js create mode 100644 js/src/tests/non262/ArrayBuffer/CloneArrayBuffer.js create mode 100644 js/src/tests/non262/ArrayBuffer/browser.js create mode 100644 js/src/tests/non262/ArrayBuffer/bug1689503.js create mode 100644 js/src/tests/non262/ArrayBuffer/bug1777413.js create mode 100644 js/src/tests/non262/ArrayBuffer/constructorNotCallable.js create mode 100644 js/src/tests/non262/ArrayBuffer/getter-name.js create mode 100644 js/src/tests/non262/ArrayBuffer/shell.js create mode 100644 js/src/tests/non262/ArrayBuffer/slice-species.js create mode 100644 js/src/tests/non262/AsyncGenerators/async-generator-declaration-in-modules.js create mode 100644 js/src/tests/non262/AsyncGenerators/browser.js create mode 100644 js/src/tests/non262/AsyncGenerators/create-function-parse-before-getprototype.js create mode 100644 js/src/tests/non262/AsyncGenerators/cross-compartment.js create mode 100644 js/src/tests/non262/AsyncGenerators/for-await-bad-syntax.js create mode 100644 js/src/tests/non262/AsyncGenerators/for-await-of-error.js create mode 100644 js/src/tests/non262/AsyncGenerators/shell.js create mode 100644 js/src/tests/non262/AsyncIterator/asynciterator.js create mode 100644 js/src/tests/non262/AsyncIterator/constructor-subclassable.js create mode 100644 js/src/tests/non262/AsyncIterator/constructor-throw-when-called-directly.js create mode 100644 js/src/tests/non262/AsyncIterator/constructor-throw-without-new.js create mode 100644 js/src/tests/non262/AsyncIterator/constructor.js create mode 100644 js/src/tests/non262/AsyncIterator/length.js create mode 100644 js/src/tests/non262/AsyncIterator/name.js create mode 100644 js/src/tests/non262/AsyncIterator/proto.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/asIndexedPairs/asIndexedPairs.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/asIndexedPairs/length.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/asIndexedPairs/name.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/async-iterator-helpers-from-other-global.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/clobber-symbol.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/drop/drop-more-than-available.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/drop/drop.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/drop/length.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/drop/name.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/every/async-writes.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/every/check-fn-after-getting-iterator.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/every/coerce-result-to-boolean.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/every/descriptor.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/every/error-from-correct-realm.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/every/fn-not-callable-throws.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/every/fn-throws-close-iterator.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/every/interleaving-calls.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/every/length.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/every/name.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/every/next-throws-iterator-not-closed.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/every/proxy.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/every/return-true-if-all-match.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/every/short-circuit-on-false.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/every/this-not-iterator-throws.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/every/value-throws-iterator-not-closed.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/filter/coerce-result-to-boolean.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/filter/filter.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/filter/length.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/filter/name.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/find/async-writes.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/find/check-fn-after-getting-iterator.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/find/coerce-result-to-boolean.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/find/descriptor.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/find/error-from-correct-realm.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/find/fn-not-callable-throws.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/find/fn-throws-close-iterator.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/find/interleaving-calls.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/find/length.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/find/name.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/find/next-throws-iterator-not-closed.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/find/proxy.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/find/return-undefined-if-none-match.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/find/short-circuit-on-match.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/find/this-not-iterator-throws.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/find/value-throws-iterator-not-closed.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/flatMap/close-iterator-when-inner-complete-throws.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/flatMap/close-iterator-when-inner-next-throws.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/flatMap/close-iterator-when-inner-value-throws.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/flatMap/flatMap.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/flatMap/inner-empty-iterable.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/flatMap/inner-generator.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/flatMap/length.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/flatMap/name.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/flatMap/throw-when-inner-not-iterable.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/forEach/async-writes.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/forEach/check-fn-after-getting-iterator.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/forEach/descriptor.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/forEach/error-from-correct-realm.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/forEach/fn-not-callable-throws.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/forEach/fn-throws-close-iterator.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/forEach/forEach.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/forEach/interleaving-calls.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/forEach/length.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/forEach/name.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/forEach/next-throws-iterator-not-closed.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/forEach/proxy.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/forEach/this-not-iterator-throws.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/forEach/value-throws-iterator-not-closed.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/generator-methods-throw-on-iterator-helpers.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/iterator-helper-methods-throw-on-generators.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/lazy-methods-from-other-global.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/lazy-methods-handle-empty-iterators.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/lazy-methods-interleaved.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-closed-on-call-throws.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-closed-on-yield-throws.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-not-closed-on-next-get-then-throws.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-not-closed-on-next-promise-executor-throws.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-not-closed-on-next-returns-reject.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-not-closed-on-next-then-throws.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-not-closed-on-next-throws.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-not-closed-on-value-throws.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-returns-done-generator-finishes.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/lazy-methods-multiple-return-close-iterator-once.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/lazy-methods-multiple-throw-close-iterator-once.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/lazy-methods-mutate-iterator-after-done.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/lazy-methods-mutate-iterator.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/lazy-methods-not-close-iterator-next-reject.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/lazy-methods-pass-through-lastValue.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/lazy-methods-pass-value-through-chain.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/lazy-methods-proxy-accesses.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/lazy-methods-return-closes-iterator.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/lazy-methods-return-new-iterator-result.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/lazy-methods-throw-closes-iterator-before-next.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/lazy-methods-throw-eagerly-on-next-non-callable.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/lazy-methods-throw-eagerly-on-non-callable.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/lazy-methods-throw-eagerly-on-non-iterator.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/lazy-methods-throw-next-done-throws.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/lazy-methods-throw-next-not-object.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/lazy-methods-throw-on-reentry.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/map/length.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/map/map.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/map/name.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/reduce/accumulator-set-to-initial-value.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/reduce/async-writes.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/reduce/check-fn-after-getting-iterator.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/reduce/descriptor.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/reduce/empty-iterator-without-initial-value-throws.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/reduce/error-from-correct-realm.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/reduce/interleaving-calls.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/reduce/iterator-empty-return-initial-value.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/reduce/iterator-next-return-non-object-throws.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/reduce/left-associative.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/reduce/length.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/reduce/name.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/reduce/next-throws-iterator-not-closed.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/reduce/no-initial-value-set-accumulator-to-first-value.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/reduce/proxy.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/reduce/reduce.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/reduce/reducer-not-callable-throws.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/reduce/reducer-throws-iterator-closed.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/reduce/this-not-iterator-throws.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/reduce/value-throws-iterator-not-closed.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/some/async-writes.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/some/check-fn-after-getting-iterator.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/some/coerce-result-to-boolean.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/some/descriptor.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/some/error-from-correct-realm.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/some/fn-not-callable-throws.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/some/fn-throws-close-iterator.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/some/interleaving-calls.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/some/length.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/some/name.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/some/next-throws-iterator-not-closed.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/some/proxy.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/some/return-false-if-none-match.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/some/short-circuit-on-true.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/some/this-not-iterator-throws.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/some/value-throws-iterator-not-closed.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/take-drop-throw-eagerly-on-negative.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/take-drop-throw-eagerly-on-non-integer.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/take/close-iterator-when-none-remaining.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/take/length.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/take/name.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/take/take-more-than-available.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/take/take.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/toArray/async-writes.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/toArray/create-in-current-realm.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/toArray/descriptor.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/toArray/interleaving-calls.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/toArray/iterator-empty.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/toArray/length.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/toArray/name.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/toArray/next-throws.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/toArray/proxy.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/toArray/this-not-iterator-throws.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/toArray/toArray.js create mode 100644 js/src/tests/non262/AsyncIterator/prototype/toArray/value-throws-iterator-not-closed.js create mode 100644 js/src/tests/non262/Atomics/browser.js create mode 100644 js/src/tests/non262/Atomics/cross-compartment.js create mode 100644 js/src/tests/non262/Atomics/detached-buffers.js create mode 100644 js/src/tests/non262/Atomics/shell.js create mode 100644 js/src/tests/non262/BigInt/Number-conversion-rounding.js create mode 100644 js/src/tests/non262/BigInt/decimal.js create mode 100644 js/src/tests/non262/BigInt/large-bit-length.js create mode 100644 js/src/tests/non262/BigInt/mod.js create mode 100644 js/src/tests/non262/BigInt/property-name-guessed-name.js create mode 100644 js/src/tests/non262/BigInt/property-name.js create mode 100644 js/src/tests/non262/Boolean/15.6.4.2.js create mode 100644 js/src/tests/non262/Boolean/browser.js create mode 100644 js/src/tests/non262/Boolean/no-boolean-toJSON.js create mode 100644 js/src/tests/non262/Boolean/shell.js create mode 100644 js/src/tests/non262/DataView/browser.js create mode 100644 js/src/tests/non262/DataView/detach-after-construction.js create mode 100644 js/src/tests/non262/DataView/get-set-index-range.js create mode 100644 js/src/tests/non262/DataView/getter-name.js create mode 100644 js/src/tests/non262/DataView/shell.js create mode 100644 js/src/tests/non262/Date/15.9.4.2.js create mode 100644 js/src/tests/non262/Date/15.9.5.5-02.js create mode 100644 js/src/tests/non262/Date/15.9.5.5.js create mode 100644 js/src/tests/non262/Date/15.9.5.6.js create mode 100644 js/src/tests/non262/Date/15.9.5.7.js create mode 100644 js/src/tests/non262/Date/UTC-convert-all-arguments.js create mode 100644 js/src/tests/non262/Date/browser.js create mode 100644 js/src/tests/non262/Date/constructor-convert-all-arguments.js create mode 100644 js/src/tests/non262/Date/constructor-one-Date-argument.js create mode 100644 js/src/tests/non262/Date/constructor-one-argument.js create mode 100644 js/src/tests/non262/Date/dashed-date.js create mode 100644 js/src/tests/non262/Date/defaultvalue.js create mode 100644 js/src/tests/non262/Date/dst-offset-caching-1-of-8.js create mode 100644 js/src/tests/non262/Date/dst-offset-caching-2-of-8.js create mode 100644 js/src/tests/non262/Date/dst-offset-caching-3-of-8.js create mode 100644 js/src/tests/non262/Date/dst-offset-caching-4-of-8.js create mode 100644 js/src/tests/non262/Date/dst-offset-caching-5-of-8.js create mode 100644 js/src/tests/non262/Date/dst-offset-caching-6-of-8.js create mode 100644 js/src/tests/non262/Date/dst-offset-caching-7-of-8.js create mode 100644 js/src/tests/non262/Date/dst-offset-caching-8-of-8.js create mode 100644 js/src/tests/non262/Date/equality-to-boolean.js create mode 100644 js/src/tests/non262/Date/fractions.js create mode 100644 js/src/tests/non262/Date/non-iso.js create mode 100644 js/src/tests/non262/Date/parse-dashed-numeric-date.js create mode 100644 js/src/tests/non262/Date/parse-day-of-week.js create mode 100644 js/src/tests/non262/Date/parse-from-tostring-methods.js create mode 100644 js/src/tests/non262/Date/parse-keywords.js create mode 100644 js/src/tests/non262/Date/parse-milliseconds.js create mode 100644 js/src/tests/non262/Date/parse-month.js create mode 100644 js/src/tests/non262/Date/parse-num-preceding-alpha.js create mode 100644 js/src/tests/non262/Date/parse-period.js create mode 100644 js/src/tests/non262/Date/parse-single-number.js create mode 100644 js/src/tests/non262/Date/parse-time-zone.js create mode 100644 js/src/tests/non262/Date/parse-timezone-without-gmt.js create mode 100644 js/src/tests/non262/Date/parse-year-after-timezone.js create mode 100644 js/src/tests/non262/Date/parse-zulu-time.js create mode 100644 js/src/tests/non262/Date/prototype-is-not-a-date.js create mode 100644 js/src/tests/non262/Date/regress-188211.js create mode 100644 js/src/tests/non262/Date/regress-301738-01.js create mode 100644 js/src/tests/non262/Date/regress-309925-01.js create mode 100644 js/src/tests/non262/Date/regress-309925-02.js create mode 100644 js/src/tests/non262/Date/regress-346027.js create mode 100644 js/src/tests/non262/Date/regress-346363.js create mode 100644 js/src/tests/non262/Date/regress-452786.js create mode 100644 js/src/tests/non262/Date/reset-time-zone-cache-same-offset.js create mode 100644 js/src/tests/non262/Date/setTime-argument-shortcircuiting.js create mode 100644 js/src/tests/non262/Date/shell.js create mode 100644 js/src/tests/non262/Date/time-components-negative-zero.js create mode 100644 js/src/tests/non262/Date/time-zone-2038-pst.js create mode 100644 js/src/tests/non262/Date/time-zone-etc_localetime.js create mode 100644 js/src/tests/non262/Date/time-zone-path.js create mode 100644 js/src/tests/non262/Date/time-zone-pst.js create mode 100644 js/src/tests/non262/Date/time-zones-historic.js create mode 100644 js/src/tests/non262/Date/time-zones-imported.js create mode 100644 js/src/tests/non262/Date/time-zones-pedantic.js create mode 100644 js/src/tests/non262/Date/time-zones-posix.js create mode 100644 js/src/tests/non262/Date/time-zones.js create mode 100644 js/src/tests/non262/Date/timeclip.js create mode 100644 js/src/tests/non262/Date/to-temporal-instant.js create mode 100644 js/src/tests/non262/Date/toISOString-01.js create mode 100644 js/src/tests/non262/Date/toISOString.js create mode 100644 js/src/tests/non262/Date/toJSON-01.js create mode 100644 js/src/tests/non262/Date/toPrimitive.js create mode 100644 js/src/tests/non262/Date/toString-generic.js create mode 100644 js/src/tests/non262/Date/toString-localized-posix.js create mode 100644 js/src/tests/non262/Date/toString-localized.js create mode 100644 js/src/tests/non262/Date/two-digit-years.js create mode 100644 js/src/tests/non262/Error/AggregateError.js create mode 100644 js/src/tests/non262/Error/browser.js create mode 100644 js/src/tests/non262/Error/constructor-ordering.js create mode 100644 js/src/tests/non262/Error/constructor-proto.js create mode 100644 js/src/tests/non262/Error/prototype-properties.js create mode 100644 js/src/tests/non262/Error/prototype.js create mode 100644 js/src/tests/non262/Error/regress-354246.js create mode 100644 js/src/tests/non262/Error/regress-412324.js create mode 100644 js/src/tests/non262/Error/regress-465377.js create mode 100644 js/src/tests/non262/Error/shell.js create mode 100644 js/src/tests/non262/Exceptions/browser.js create mode 100644 js/src/tests/non262/Exceptions/catchguard-002-n.js create mode 100644 js/src/tests/non262/Exceptions/catchguard-003-n.js create mode 100644 js/src/tests/non262/Exceptions/error-expando-reconfigure.js create mode 100644 js/src/tests/non262/Exceptions/error-property-enumerability.js create mode 100644 js/src/tests/non262/Exceptions/errstack-001.js create mode 100644 js/src/tests/non262/Exceptions/regress-121658.js create mode 100644 js/src/tests/non262/Exceptions/regress-123002.js create mode 100644 js/src/tests/non262/Exceptions/regress-181654.js create mode 100644 js/src/tests/non262/Exceptions/regress-181914.js create mode 100644 js/src/tests/non262/Exceptions/regress-257751.js create mode 100644 js/src/tests/non262/Exceptions/regress-273931.js create mode 100644 js/src/tests/non262/Exceptions/regress-332472.js create mode 100644 js/src/tests/non262/Exceptions/regress-333728.js create mode 100644 js/src/tests/non262/Exceptions/regress-342359.js create mode 100644 js/src/tests/non262/Exceptions/regress-347674.js create mode 100644 js/src/tests/non262/Exceptions/regress-350650-n.js create mode 100644 js/src/tests/non262/Exceptions/regress-350837.js create mode 100644 js/src/tests/non262/Exceptions/regress-58946.js create mode 100644 js/src/tests/non262/Exceptions/regress-95101.js create mode 100644 js/src/tests/non262/Exceptions/shell.js create mode 100644 js/src/tests/non262/Function/10.1.6-01.js create mode 100644 js/src/tests/non262/Function/10.1.6.js create mode 100644 js/src/tests/non262/Function/10.2.1.1.6.js create mode 100644 js/src/tests/non262/Function/15.3.4.3-01.js create mode 100644 js/src/tests/non262/Function/Function-arguments-gc.js create mode 100644 js/src/tests/non262/Function/Function-prototype.js create mode 100644 js/src/tests/non262/Function/Function-with-eval.js create mode 100644 js/src/tests/non262/Function/Object-toSource.js create mode 100644 js/src/tests/non262/Function/arguments-caller-callee.js create mode 100644 js/src/tests/non262/Function/arguments-extra-property.js create mode 100644 js/src/tests/non262/Function/arguments-iterator.js create mode 100644 js/src/tests/non262/Function/arguments-parameter-shadowing.js create mode 100644 js/src/tests/non262/Function/arguments-property-attributes.js create mode 100644 js/src/tests/non262/Function/arrow-has-duplicated.js create mode 100644 js/src/tests/non262/Function/bound-length-and-name.js create mode 100644 js/src/tests/non262/Function/bound-non-constructable.js create mode 100644 js/src/tests/non262/Function/bound-prototype.js create mode 100644 js/src/tests/non262/Function/browser.js create mode 100644 js/src/tests/non262/Function/builtin-no-construct.js create mode 100644 js/src/tests/non262/Function/builtin-no-prototype.js create mode 100644 js/src/tests/non262/Function/configurable-length-builtins.js create mode 100644 js/src/tests/non262/Function/configurable-length.js create mode 100644 js/src/tests/non262/Function/construct-bound-proxy-with-many-arguments.js create mode 100644 js/src/tests/non262/Function/constructor-binding.js create mode 100644 js/src/tests/non262/Function/create-function-parse-before-getprototype.js create mode 100644 js/src/tests/non262/Function/function-bind.js create mode 100644 js/src/tests/non262/Function/function-call.js create mode 100644 js/src/tests/non262/Function/function-caller-restrictions.js create mode 100644 js/src/tests/non262/Function/function-caller.js create mode 100644 js/src/tests/non262/Function/function-constructor-toString-arguments-before-parsing-params.js create mode 100644 js/src/tests/non262/Function/function-name-assignment.js create mode 100644 js/src/tests/non262/Function/function-name-binding.js create mode 100644 js/src/tests/non262/Function/function-name-class.js create mode 100644 js/src/tests/non262/Function/function-name-computed-01.js create mode 100644 js/src/tests/non262/Function/function-name-computed-02.js create mode 100644 js/src/tests/non262/Function/function-name-for.js create mode 100644 js/src/tests/non262/Function/function-name-method.js create mode 100644 js/src/tests/non262/Function/function-name-property.js create mode 100644 js/src/tests/non262/Function/function-name.js create mode 100644 js/src/tests/non262/Function/function-toString-builtin-name.js create mode 100644 js/src/tests/non262/Function/function-toString-builtin.js create mode 100644 js/src/tests/non262/Function/get-function-realm.js create mode 100644 js/src/tests/non262/Function/has-instance-jitted.js create mode 100644 js/src/tests/non262/Function/has-instance.js create mode 100644 js/src/tests/non262/Function/implicit-this-in-parameter-expression.js create mode 100644 js/src/tests/non262/Function/invalid-parameter-list.js create mode 100644 js/src/tests/non262/Function/length-with-destructuring-and-parameter-expression.js create mode 100644 js/src/tests/non262/Function/line-terminator-before-arrow.js create mode 100644 js/src/tests/non262/Function/method-has-duplicated.js create mode 100644 js/src/tests/non262/Function/parameter-redeclaration.js create mode 100644 js/src/tests/non262/Function/redefine-arguments-length.js create mode 100644 js/src/tests/non262/Function/regress-123371.js create mode 100644 js/src/tests/non262/Function/regress-131964.js create mode 100644 js/src/tests/non262/Function/regress-137181.js create mode 100644 js/src/tests/non262/Function/regress-178389.js create mode 100644 js/src/tests/non262/Function/regress-193555.js create mode 100644 js/src/tests/non262/Function/regress-222029-001.js create mode 100644 js/src/tests/non262/Function/regress-222029-002.js create mode 100644 js/src/tests/non262/Function/regress-292215.js create mode 100644 js/src/tests/non262/Function/regress-313570.js create mode 100644 js/src/tests/non262/Function/regress-338121-01.js create mode 100644 js/src/tests/non262/Function/regress-338121-02.js create mode 100644 js/src/tests/non262/Function/regress-344052.js create mode 100644 js/src/tests/non262/Function/regress-364023.js create mode 100644 js/src/tests/non262/Function/regress-49286.js create mode 100644 js/src/tests/non262/Function/regress-518103.js create mode 100644 js/src/tests/non262/Function/regress-524826.js create mode 100644 js/src/tests/non262/Function/regress-528082.js create mode 100644 js/src/tests/non262/Function/regress-533254.js create mode 100644 js/src/tests/non262/Function/regress-545980.js create mode 100644 js/src/tests/non262/Function/regress-58274.js create mode 100644 js/src/tests/non262/Function/regress-85880.js create mode 100644 js/src/tests/non262/Function/regress-94506.js create mode 100644 js/src/tests/non262/Function/regress-97921.js create mode 100644 js/src/tests/non262/Function/rest-has-duplicated.js create mode 100644 js/src/tests/non262/Function/rest-parameter-names.js create mode 100644 js/src/tests/non262/Function/return-finally.js create mode 100644 js/src/tests/non262/Function/shell.js create mode 100644 js/src/tests/non262/Function/spread-iterator-primitive.js create mode 100644 js/src/tests/non262/Function/strict-arguments.js create mode 100644 js/src/tests/non262/Function/throw-type-error.js create mode 100644 js/src/tests/non262/GC/browser.js create mode 100644 js/src/tests/non262/GC/regress-104584.js create mode 100644 js/src/tests/non262/GC/regress-203278-2.js create mode 100644 js/src/tests/non262/GC/regress-203278-3.js create mode 100644 js/src/tests/non262/GC/regress-278725.js create mode 100644 js/src/tests/non262/GC/regress-306788.js create mode 100644 js/src/tests/non262/GC/regress-311497.js create mode 100644 js/src/tests/non262/GC/regress-313276.js create mode 100644 js/src/tests/non262/GC/regress-313479.js create mode 100644 js/src/tests/non262/GC/regress-316885-01.js create mode 100644 js/src/tests/non262/GC/regress-316885-02.js create mode 100644 js/src/tests/non262/GC/regress-316885-03.js create mode 100644 js/src/tests/non262/GC/regress-319980-01.js create mode 100644 js/src/tests/non262/GC/regress-324278.js create mode 100644 js/src/tests/non262/GC/regress-331719.js create mode 100644 js/src/tests/non262/GC/regress-338653.js create mode 100644 js/src/tests/non262/GC/regress-341877-01.js create mode 100644 js/src/tests/non262/GC/regress-341877-02.js create mode 100644 js/src/tests/non262/GC/regress-348532.js create mode 100644 js/src/tests/non262/GC/regress-352606.js create mode 100644 js/src/tests/non262/GC/regress-383269-01.js create mode 100644 js/src/tests/non262/GC/regress-383269-02.js create mode 100644 js/src/tests/non262/GC/regress-390078.js create mode 100644 js/src/tests/non262/GC/regress-418128.js create mode 100644 js/src/tests/non262/GC/regress-440558.js create mode 100644 js/src/tests/non262/GC/shell.js create mode 100644 js/src/tests/non262/Intl/Array/shell.js create mode 100644 js/src/tests/non262/Intl/Array/toLocaleString-date.js create mode 100644 js/src/tests/non262/Intl/Array/toLocaleString-number.js create mode 100644 js/src/tests/non262/Intl/Array/toLocaleString.js create mode 100644 js/src/tests/non262/Intl/Collator/big5han-gb2312han.js create mode 100644 js/src/tests/non262/Intl/Collator/browser.js create mode 100644 js/src/tests/non262/Intl/Collator/call.js create mode 100644 js/src/tests/non262/Intl/Collator/caseFirst.js create mode 100644 js/src/tests/non262/Intl/Collator/collation.js create mode 100644 js/src/tests/non262/Intl/Collator/compare.js create mode 100644 js/src/tests/non262/Intl/Collator/construct-newtarget.js create mode 100644 js/src/tests/non262/Intl/Collator/cross-compartment.js create mode 100644 js/src/tests/non262/Intl/Collator/ignorePunctuation.js create mode 100644 js/src/tests/non262/Intl/Collator/implicithan.js create mode 100644 js/src/tests/non262/Intl/Collator/shell.js create mode 100644 js/src/tests/non262/Intl/Collator/supportedLocalesOf.js create mode 100644 js/src/tests/non262/Intl/Collator/toStringTag.js create mode 100644 js/src/tests/non262/Intl/Date/browser.js create mode 100644 js/src/tests/non262/Intl/Date/shell.js create mode 100644 js/src/tests/non262/Intl/Date/toLocaleDateString_timeZone.js create mode 100644 js/src/tests/non262/Intl/Date/toLocaleString_timeZone.js create mode 100644 js/src/tests/non262/Intl/Date/toLocaleTimeString_timeZone.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/browser.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/calendar-aliases.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/calendar-option.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/call.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/construct-newtarget.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/cross-compartment.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/dateTimeStyle.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/day-period-hour-cycle.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/day-period-standalone.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/day-period.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/era.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/extended-time-zone-names.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/field-widths.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/format-timeZone-offset.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/format.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/formatRange-gregorian-proleptic.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/formatRange-hour-cycle.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/formatRange-matches-format-output.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/formatRange-original-skeleton.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/formatRange-timeZone-offset.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/formatRange-timeZoneName-matches-format.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/formatRange-timeZoneName.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/formatToParts.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/format_timeZone-non-meta.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/format_timeZone.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/fractional-second-digits-append-item.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/fractional-second-digits.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/hourCycle.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/implied-script-has-consistent-output.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/islamic.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/japanese-gannen-year.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/mozExtensions.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/numberingSystem-option.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/options-property-accesses.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/related-year.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/shell.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/standalone-month.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/supportedLocalesOf.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/timeZone.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/timeZone_backward_links.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/timeZone_backzone.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/timeZone_backzone_links.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/timeZone_notbackward_links.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/timeZone_version.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/toStringTag.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/tz-environment-variable.js create mode 100644 js/src/tests/non262/Intl/DateTimeFormat/unwrapping.js create mode 100644 js/src/tests/non262/Intl/DisplayNames/abbreviated.js create mode 100644 js/src/tests/non262/Intl/DisplayNames/alias-and-parent-locales.js create mode 100644 js/src/tests/non262/Intl/DisplayNames/browser.js create mode 100644 js/src/tests/non262/Intl/DisplayNames/calendar.js create mode 100644 js/src/tests/non262/Intl/DisplayNames/currency.js create mode 100644 js/src/tests/non262/Intl/DisplayNames/dateTimeField.js create mode 100644 js/src/tests/non262/Intl/DisplayNames/dayPeriod.js create mode 100644 js/src/tests/non262/Intl/DisplayNames/language-dialect.js create mode 100644 js/src/tests/non262/Intl/DisplayNames/language.js create mode 100644 js/src/tests/non262/Intl/DisplayNames/month-calendar.js create mode 100644 js/src/tests/non262/Intl/DisplayNames/month.js create mode 100644 js/src/tests/non262/Intl/DisplayNames/quarter.js create mode 100644 js/src/tests/non262/Intl/DisplayNames/region.js create mode 100644 js/src/tests/non262/Intl/DisplayNames/script.js create mode 100644 js/src/tests/non262/Intl/DisplayNames/shell.js create mode 100644 js/src/tests/non262/Intl/DisplayNames/weekday.js create mode 100644 js/src/tests/non262/Intl/ListFormat/browser.js create mode 100644 js/src/tests/non262/Intl/ListFormat/conjunction-type.js create mode 100644 js/src/tests/non262/Intl/ListFormat/cross-compartment.js create mode 100644 js/src/tests/non262/Intl/ListFormat/disjunction-type.js create mode 100644 js/src/tests/non262/Intl/ListFormat/same-compartment.js create mode 100644 js/src/tests/non262/Intl/ListFormat/shell.js create mode 100644 js/src/tests/non262/Intl/ListFormat/supported-locales.js create mode 100644 js/src/tests/non262/Intl/ListFormat/unit-type.js create mode 100644 js/src/tests/non262/Intl/Locale/apply-options-to-tag-canonicalize-twice.js create mode 100644 js/src/tests/non262/Intl/Locale/browser.js create mode 100644 js/src/tests/non262/Intl/Locale/coerce-options-before-validating-tag.js create mode 100644 js/src/tests/non262/Intl/Locale/cross-compartment.js create mode 100644 js/src/tests/non262/Intl/Locale/legacy.js create mode 100644 js/src/tests/non262/Intl/Locale/likely-subtags-generated.js create mode 100644 js/src/tests/non262/Intl/Locale/likely-subtags.js create mode 100644 js/src/tests/non262/Intl/Locale/same-compartment.js create mode 100644 js/src/tests/non262/Intl/Locale/shell.js create mode 100644 js/src/tests/non262/Intl/Locale/surface.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/StringBuffer.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/bigint-int64.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/browser.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/call.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/construct-newtarget.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/cross-compartment.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/currency-narrow-symbol.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/currency-sign-accounting.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/duplicate-singleton-variant.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/format-as-code-or-name.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/format-string.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/format.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/formatRange-BigInt.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/formatRange.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-compact.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-currency.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-percent.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-signDisplay.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-unit.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/formatRangeToParts.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/formatToParts.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/formatting-NaN.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/negativeZeroFractionDigits.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/notation-compact-long.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/notation-compact-short.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/notation-compact-with-fraction-digits.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/notation-engineering.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/notation-scientific.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/numberingSystem-format.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/numberingSystem-option.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/options-emulate-undefined.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/remove-unicode-extensions.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/rounding-increment.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/rounding-mode.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/rounding-priority.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/shell.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/sign-display.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/significantDigitsOfZero.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/supportedLocalesOf.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/toStringTag.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/trailing-zero-display.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/unit-compound-combinations.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/unit-formatToParts-has-unit-field.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/unit-well-formed.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/unit.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/unwrapping.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/use-grouping-bool-string.js create mode 100644 js/src/tests/non262/Intl/NumberFormat/use-grouping.js create mode 100644 js/src/tests/non262/Intl/PluralRules/browser.js create mode 100644 js/src/tests/non262/Intl/PluralRules/call.js create mode 100644 js/src/tests/non262/Intl/PluralRules/construct-newtarget.js create mode 100644 js/src/tests/non262/Intl/PluralRules/cross-compartment.js create mode 100644 js/src/tests/non262/Intl/PluralRules/negativeZeroFractionDigits.js create mode 100644 js/src/tests/non262/Intl/PluralRules/number-options.js create mode 100644 js/src/tests/non262/Intl/PluralRules/pluralrules.js create mode 100644 js/src/tests/non262/Intl/PluralRules/resolvedOptions-overridden-species.js create mode 100644 js/src/tests/non262/Intl/PluralRules/rounding.js create mode 100644 js/src/tests/non262/Intl/PluralRules/select.js create mode 100644 js/src/tests/non262/Intl/PluralRules/selectRange.js create mode 100644 js/src/tests/non262/Intl/PluralRules/shell.js create mode 100644 js/src/tests/non262/Intl/PluralRules/supportedLocalesOf.js create mode 100644 js/src/tests/non262/Intl/README.txt create mode 100644 js/src/tests/non262/Intl/RelativeTimeFormat/browser.js create mode 100644 js/src/tests/non262/Intl/RelativeTimeFormat/construct-newtarget.js create mode 100644 js/src/tests/non262/Intl/RelativeTimeFormat/cross-compartment.js create mode 100644 js/src/tests/non262/Intl/RelativeTimeFormat/format.js create mode 100644 js/src/tests/non262/Intl/RelativeTimeFormat/locale-fallback-handling.js create mode 100644 js/src/tests/non262/Intl/RelativeTimeFormat/numbering-system.js create mode 100644 js/src/tests/non262/Intl/RelativeTimeFormat/numberingSystem-option.js create mode 100644 js/src/tests/non262/Intl/RelativeTimeFormat/relativetimeformat.js create mode 100644 js/src/tests/non262/Intl/RelativeTimeFormat/shell.js create mode 100644 js/src/tests/non262/Intl/RelativeTimeFormat/supportedLocalesOf.js create mode 100644 js/src/tests/non262/Intl/Segmenter/browser.js create mode 100644 js/src/tests/non262/Intl/Segmenter/cross-compartment.js create mode 100644 js/src/tests/non262/Intl/Segmenter/grapheme-latin1.js create mode 100644 js/src/tests/non262/Intl/Segmenter/grapheme.js create mode 100644 js/src/tests/non262/Intl/Segmenter/refresh-text-asan.js create mode 100644 js/src/tests/non262/Intl/Segmenter/sentence-latin.js create mode 100644 js/src/tests/non262/Intl/Segmenter/sentence.js create mode 100644 js/src/tests/non262/Intl/Segmenter/shell.js create mode 100644 js/src/tests/non262/Intl/Segmenter/surrogate-pair-split.js create mode 100644 js/src/tests/non262/Intl/Segmenter/word-latin1.js create mode 100644 js/src/tests/non262/Intl/Segmenter/word.js create mode 100644 js/src/tests/non262/Intl/String/shell.js create mode 100644 js/src/tests/non262/Intl/String/toLocaleLowerCase.js create mode 100644 js/src/tests/non262/Intl/String/toLocaleUpperCase.js create mode 100644 js/src/tests/non262/Intl/TypedArray/shell.js create mode 100644 js/src/tests/non262/Intl/TypedArray/toLocaleString.js create mode 100644 js/src/tests/non262/Intl/available-locales-implied-script.js create mode 100644 js/src/tests/non262/Intl/available-locales-resolved.js create mode 100644 js/src/tests/non262/Intl/available-locales-supported.js create mode 100644 js/src/tests/non262/Intl/best-available-locale-from-default-locale.js create mode 100644 js/src/tests/non262/Intl/browser.js create mode 100644 js/src/tests/non262/Intl/default-locale-shell.js create mode 100644 js/src/tests/non262/Intl/duplicate-variants.js create mode 100644 js/src/tests/non262/Intl/extensions/browser.js create mode 100644 js/src/tests/non262/Intl/extensions/options-value-emulates-undefined.js create mode 100644 js/src/tests/non262/Intl/extensions/shell.js create mode 100644 js/src/tests/non262/Intl/extensions/unicode-extension-sequences.js create mode 100644 js/src/tests/non262/Intl/fallback-symbol.js create mode 100644 js/src/tests/non262/Intl/four-letter-language-codes.js create mode 100644 js/src/tests/non262/Intl/getCalendarInfo.js create mode 100644 js/src/tests/non262/Intl/getCanonicalLocales-overridden-arg-length.js create mode 100644 js/src/tests/non262/Intl/getCanonicalLocales-overridden-push.js create mode 100644 js/src/tests/non262/Intl/getCanonicalLocales-overridden-set.js create mode 100644 js/src/tests/non262/Intl/getCanonicalLocales-overridden-species.js create mode 100644 js/src/tests/non262/Intl/getCanonicalLocales-weird-cases.js create mode 100644 js/src/tests/non262/Intl/getCanonicalLocales-with-duplicates.js create mode 100644 js/src/tests/non262/Intl/getCanonicalLocales.js create mode 100644 js/src/tests/non262/Intl/legacy-and-sign-locales-with-unicode-extensions.js create mode 100644 js/src/tests/non262/Intl/resolved-locale-sorted-unicode-extension-keys.js create mode 100644 js/src/tests/non262/Intl/shell.js create mode 100644 js/src/tests/non262/Intl/supportedValuesOf-calendar.js create mode 100644 js/src/tests/non262/Intl/supportedValuesOf-collation.js create mode 100644 js/src/tests/non262/Intl/supportedValuesOf-currency.js create mode 100644 js/src/tests/non262/Intl/supportedValuesOf-numberingSystem.js create mode 100644 js/src/tests/non262/Intl/supportedValuesOf-timeZones-canonical.js create mode 100644 js/src/tests/non262/Intl/supportedValuesOf-timeZones.js create mode 100644 js/src/tests/non262/Intl/supportedValuesOf-unit.js create mode 100644 js/src/tests/non262/Intl/tolower-ascii-equivalent.js create mode 100644 js/src/tests/non262/Intl/unicode-bcp47-locale-ids-extlangs.js create mode 100644 js/src/tests/non262/Intl/unicode-bcp47-locale-ids-language-mappings.js create mode 100644 js/src/tests/non262/Intl/unicode-bcp47-locale-ids-languages-mappings-complex.js create mode 100644 js/src/tests/non262/Intl/unicode-bcp47-locale-ids-legacy.js create mode 100644 js/src/tests/non262/Intl/unicode-bcp47-locale-ids-region-and-subdivision.js create mode 100644 js/src/tests/non262/Intl/unicode-bcp47-locale-ids-region-mappings-complex.js create mode 100644 js/src/tests/non262/Intl/unicode-bcp47-locale-ids-region-mappings.js create mode 100644 js/src/tests/non262/Intl/unicode-bcp47-locale-ids-sign-languages.js create mode 100644 js/src/tests/non262/Intl/unicode-bcp47-locale-ids-transformed-ext.js create mode 100644 js/src/tests/non262/Intl/unicode-bcp47-locale-ids-unicode-ext.js create mode 100644 js/src/tests/non262/Intl/unicode-bcp47-locale-ids-variants-legacy-mappings.js create mode 100644 js/src/tests/non262/Intl/unicode-bcp47-locale-ids-variants-sorted.js create mode 100644 js/src/tests/non262/Intl/variant-with-preferred-value.js create mode 100644 js/src/tests/non262/Iterator/constructor-subclassable.js create mode 100644 js/src/tests/non262/Iterator/constructor-throw-when-called-directly.js create mode 100644 js/src/tests/non262/Iterator/constructor-throw-without-new.js create mode 100644 js/src/tests/non262/Iterator/constructor.js create mode 100644 js/src/tests/non262/Iterator/from/Iterator.from-descriptor.js create mode 100644 js/src/tests/non262/Iterator/from/Iterator.from-length.js create mode 100644 js/src/tests/non262/Iterator/from/Iterator.from-name.js create mode 100644 js/src/tests/non262/Iterator/from/call-from-with-different-this.js create mode 100644 js/src/tests/non262/Iterator/from/iterator-not-callable-throws.js create mode 100644 js/src/tests/non262/Iterator/from/modify-next.js create mode 100644 js/src/tests/non262/Iterator/from/modify-return.js create mode 100644 js/src/tests/non262/Iterator/from/o-not-object-throws.js create mode 100644 js/src/tests/non262/Iterator/from/proxy-not-wrapped.js create mode 100644 js/src/tests/non262/Iterator/from/proxy-wrap-next.js create mode 100644 js/src/tests/non262/Iterator/from/proxy-wrap-return.js create mode 100644 js/src/tests/non262/Iterator/from/return-iterator-if-iterable.js create mode 100644 js/src/tests/non262/Iterator/from/return-wrapper-if-not-iterable.js create mode 100644 js/src/tests/non262/Iterator/from/return-wrapper-if-not-iterator-instance.js create mode 100644 js/src/tests/non262/Iterator/from/wrap-functions-on-other-global.js create mode 100644 js/src/tests/non262/Iterator/from/wrap-method-with-non-wrap-this-throws.js create mode 100644 js/src/tests/non262/Iterator/from/wrap-new-global.js create mode 100644 js/src/tests/non262/Iterator/from/wrap-next-forwards-value.js create mode 100644 js/src/tests/non262/Iterator/from/wrap-next-not-object-throws.js create mode 100644 js/src/tests/non262/Iterator/from/wrap-return-closes-iterator.js create mode 100644 js/src/tests/non262/Iterator/iterator.js create mode 100644 js/src/tests/non262/Iterator/length.js create mode 100644 js/src/tests/non262/Iterator/name.js create mode 100644 js/src/tests/non262/Iterator/proto.js create mode 100644 js/src/tests/non262/Iterator/prototype/drop/drop-more-than-available.js create mode 100644 js/src/tests/non262/Iterator/prototype/drop/drop.js create mode 100644 js/src/tests/non262/Iterator/prototype/drop/length.js create mode 100644 js/src/tests/non262/Iterator/prototype/drop/name.js create mode 100644 js/src/tests/non262/Iterator/prototype/every/check-fn-after-getting-iterator.js create mode 100644 js/src/tests/non262/Iterator/prototype/every/coerce-result-to-boolean.js create mode 100644 js/src/tests/non262/Iterator/prototype/every/descriptor.js create mode 100644 js/src/tests/non262/Iterator/prototype/every/error-from-correct-realm.js create mode 100644 js/src/tests/non262/Iterator/prototype/every/fn-not-callable-throws.js create mode 100644 js/src/tests/non262/Iterator/prototype/every/fn-throws-close-iterator.js create mode 100644 js/src/tests/non262/Iterator/prototype/every/length.js create mode 100644 js/src/tests/non262/Iterator/prototype/every/name.js create mode 100644 js/src/tests/non262/Iterator/prototype/every/next-throws-iterator-not-closed.js create mode 100644 js/src/tests/non262/Iterator/prototype/every/proxy.js create mode 100644 js/src/tests/non262/Iterator/prototype/every/return-true-if-all-match.js create mode 100644 js/src/tests/non262/Iterator/prototype/every/short-circuit-on-false.js create mode 100644 js/src/tests/non262/Iterator/prototype/every/this-not-iterator-throws.js create mode 100644 js/src/tests/non262/Iterator/prototype/every/value-throws-iterator-not-closed.js create mode 100644 js/src/tests/non262/Iterator/prototype/filter/coerce-result-to-boolean.js create mode 100644 js/src/tests/non262/Iterator/prototype/filter/filter.js create mode 100644 js/src/tests/non262/Iterator/prototype/filter/length.js create mode 100644 js/src/tests/non262/Iterator/prototype/filter/name.js create mode 100644 js/src/tests/non262/Iterator/prototype/find/check-fn-after-getting-iterator.js create mode 100644 js/src/tests/non262/Iterator/prototype/find/coerce-result-to-boolean.js create mode 100644 js/src/tests/non262/Iterator/prototype/find/descriptor.js create mode 100644 js/src/tests/non262/Iterator/prototype/find/error-from-correct-realm.js create mode 100644 js/src/tests/non262/Iterator/prototype/find/fn-not-callable-throws.js create mode 100644 js/src/tests/non262/Iterator/prototype/find/fn-throws-close-iterator.js create mode 100644 js/src/tests/non262/Iterator/prototype/find/length.js create mode 100644 js/src/tests/non262/Iterator/prototype/find/name.js create mode 100644 js/src/tests/non262/Iterator/prototype/find/next-throws-iterator-not-closed.js create mode 100644 js/src/tests/non262/Iterator/prototype/find/proxy.js create mode 100644 js/src/tests/non262/Iterator/prototype/find/return-undefined-if-none-match.js create mode 100644 js/src/tests/non262/Iterator/prototype/find/short-circuit-on-match.js create mode 100644 js/src/tests/non262/Iterator/prototype/find/this-not-iterator-throws.js create mode 100644 js/src/tests/non262/Iterator/prototype/find/value-throws-iterator-not-closed.js create mode 100644 js/src/tests/non262/Iterator/prototype/flatMap/close-iterator-when-inner-complete-throws.js create mode 100644 js/src/tests/non262/Iterator/prototype/flatMap/close-iterator-when-inner-next-throws.js create mode 100644 js/src/tests/non262/Iterator/prototype/flatMap/close-iterator-when-inner-value-throws.js create mode 100644 js/src/tests/non262/Iterator/prototype/flatMap/flatMap.js create mode 100644 js/src/tests/non262/Iterator/prototype/flatMap/inner-empty-iterable.js create mode 100644 js/src/tests/non262/Iterator/prototype/flatMap/inner-generator.js create mode 100644 js/src/tests/non262/Iterator/prototype/flatMap/length.js create mode 100644 js/src/tests/non262/Iterator/prototype/flatMap/name.js create mode 100644 js/src/tests/non262/Iterator/prototype/flatMap/throw-when-inner-not-iterable.js create mode 100644 js/src/tests/non262/Iterator/prototype/forEach/check-fn-after-getting-iterator.js create mode 100644 js/src/tests/non262/Iterator/prototype/forEach/descriptor.js create mode 100644 js/src/tests/non262/Iterator/prototype/forEach/error-from-correct-realm.js create mode 100644 js/src/tests/non262/Iterator/prototype/forEach/fn-not-callable-throws.js create mode 100644 js/src/tests/non262/Iterator/prototype/forEach/fn-throws-close-iterator.js create mode 100644 js/src/tests/non262/Iterator/prototype/forEach/forEach.js create mode 100644 js/src/tests/non262/Iterator/prototype/forEach/length.js create mode 100644 js/src/tests/non262/Iterator/prototype/forEach/name.js create mode 100644 js/src/tests/non262/Iterator/prototype/forEach/next-throws-iterator-not-closed.js create mode 100644 js/src/tests/non262/Iterator/prototype/forEach/proxy.js create mode 100644 js/src/tests/non262/Iterator/prototype/forEach/this-not-iterator-throws.js create mode 100644 js/src/tests/non262/Iterator/prototype/forEach/value-throws-iterator-not-closed.js create mode 100644 js/src/tests/non262/Iterator/prototype/generator-methods-throw-on-iterator-helpers.js create mode 100644 js/src/tests/non262/Iterator/prototype/iterator-helper-methods-throw-on-generators.js create mode 100644 js/src/tests/non262/Iterator/prototype/iterator-helpers-from-other-global.js create mode 100644 js/src/tests/non262/Iterator/prototype/lazy-methods-from-other-global.js create mode 100644 js/src/tests/non262/Iterator/prototype/lazy-methods-handle-empty-iterators.js create mode 100644 js/src/tests/non262/Iterator/prototype/lazy-methods-interleaved.js create mode 100644 js/src/tests/non262/Iterator/prototype/lazy-methods-iterator-closed-on-call-throws.js create mode 100644 js/src/tests/non262/Iterator/prototype/lazy-methods-iterator-closed-on-yield-throws.js create mode 100644 js/src/tests/non262/Iterator/prototype/lazy-methods-iterator-not-closed-on-next-throws.js create mode 100644 js/src/tests/non262/Iterator/prototype/lazy-methods-iterator-not-closed-on-value-throws.js create mode 100644 js/src/tests/non262/Iterator/prototype/lazy-methods-iterator-returns-done-generator-finishes.js create mode 100644 js/src/tests/non262/Iterator/prototype/lazy-methods-multiple-return-close-iterator-once.js create mode 100644 js/src/tests/non262/Iterator/prototype/lazy-methods-pass-through-lastValue.js create mode 100644 js/src/tests/non262/Iterator/prototype/lazy-methods-pass-value-through-chain.js create mode 100644 js/src/tests/non262/Iterator/prototype/lazy-methods-proxy-accesses.js create mode 100644 js/src/tests/non262/Iterator/prototype/lazy-methods-reentry-not-close-iterator.js create mode 100644 js/src/tests/non262/Iterator/prototype/lazy-methods-return-closes-iterator.js create mode 100644 js/src/tests/non262/Iterator/prototype/lazy-methods-return-new-iterator-result.js create mode 100644 js/src/tests/non262/Iterator/prototype/lazy-methods-throw-eagerly-on-next-non-callable.js create mode 100644 js/src/tests/non262/Iterator/prototype/lazy-methods-throw-eagerly-on-non-callable.js create mode 100644 js/src/tests/non262/Iterator/prototype/lazy-methods-throw-eagerly-on-non-iterator.js create mode 100644 js/src/tests/non262/Iterator/prototype/lazy-methods-throw-next-done-throws.js create mode 100644 js/src/tests/non262/Iterator/prototype/lazy-methods-throw-next-not-object.js create mode 100644 js/src/tests/non262/Iterator/prototype/lazy-methods-throw-on-reentry.js create mode 100644 js/src/tests/non262/Iterator/prototype/map/call-next-on-iterator-while-iterating.js create mode 100644 js/src/tests/non262/Iterator/prototype/map/clobber-symbol.js create mode 100644 js/src/tests/non262/Iterator/prototype/map/interleaved-map-calls.js create mode 100644 js/src/tests/non262/Iterator/prototype/map/length.js create mode 100644 js/src/tests/non262/Iterator/prototype/map/map.js create mode 100644 js/src/tests/non262/Iterator/prototype/map/mapper-not-callable-throw.js create mode 100644 js/src/tests/non262/Iterator/prototype/map/mutate-iterator-after-done.js create mode 100644 js/src/tests/non262/Iterator/prototype/map/mutate-iterator.js create mode 100644 js/src/tests/non262/Iterator/prototype/map/name.js create mode 100644 js/src/tests/non262/Iterator/prototype/map/output-at-generator-end.js create mode 100644 js/src/tests/non262/Iterator/prototype/map/pass-lastValue-to-next.js create mode 100644 js/src/tests/non262/Iterator/prototype/map/proxy-abrupt-completion-in-iteratorValue.js create mode 100644 js/src/tests/non262/Iterator/prototype/map/proxy-abrupt-completion-in-yield.js create mode 100644 js/src/tests/non262/Iterator/prototype/map/proxy-abrupt-completion.js create mode 100644 js/src/tests/non262/Iterator/prototype/map/proxy-accesses.js create mode 100644 js/src/tests/non262/Iterator/prototype/map/reenter-map-generator-from-mapper.js create mode 100644 js/src/tests/non262/Iterator/prototype/map/this-not-iterator-throw.js create mode 100644 js/src/tests/non262/Iterator/prototype/map/this-value-array-throws.js create mode 100644 js/src/tests/non262/Iterator/prototype/map/throw-when-iterator-returns-non-object.js create mode 100644 js/src/tests/non262/Iterator/prototype/map/values-pass-through-chained-maps-to-next.js create mode 100644 js/src/tests/non262/Iterator/prototype/reduce/accumulator-set-to-initial-value.js create mode 100644 js/src/tests/non262/Iterator/prototype/reduce/check-fn-after-getting-iterator.js create mode 100644 js/src/tests/non262/Iterator/prototype/reduce/descriptor.js create mode 100644 js/src/tests/non262/Iterator/prototype/reduce/empty-iterator-without-initial-value-throws.js create mode 100644 js/src/tests/non262/Iterator/prototype/reduce/error-from-correct-realm.js create mode 100644 js/src/tests/non262/Iterator/prototype/reduce/iterator-empty-return-initial-value.js create mode 100644 js/src/tests/non262/Iterator/prototype/reduce/iterator-next-return-non-object-throws.js create mode 100644 js/src/tests/non262/Iterator/prototype/reduce/left-associative.js create mode 100644 js/src/tests/non262/Iterator/prototype/reduce/length.js create mode 100644 js/src/tests/non262/Iterator/prototype/reduce/name.js create mode 100644 js/src/tests/non262/Iterator/prototype/reduce/next-throws-iterator-not-closed.js create mode 100644 js/src/tests/non262/Iterator/prototype/reduce/no-initial-value-set-accumulator-to-first-value.js create mode 100644 js/src/tests/non262/Iterator/prototype/reduce/proxy.js create mode 100644 js/src/tests/non262/Iterator/prototype/reduce/reduce.js create mode 100644 js/src/tests/non262/Iterator/prototype/reduce/reducer-not-callable-throws.js create mode 100644 js/src/tests/non262/Iterator/prototype/reduce/reducer-throws-iterator-closed.js create mode 100644 js/src/tests/non262/Iterator/prototype/reduce/this-not-iterator-throws.js create mode 100644 js/src/tests/non262/Iterator/prototype/reduce/value-throws-iterator-not-closed.js create mode 100644 js/src/tests/non262/Iterator/prototype/some/check-fn-after-getting-iterator.js create mode 100644 js/src/tests/non262/Iterator/prototype/some/coerce-result-to-boolean.js create mode 100644 js/src/tests/non262/Iterator/prototype/some/descriptor.js create mode 100644 js/src/tests/non262/Iterator/prototype/some/error-from-correct-realm.js create mode 100644 js/src/tests/non262/Iterator/prototype/some/fn-not-callable-throws.js create mode 100644 js/src/tests/non262/Iterator/prototype/some/fn-throws-close-iterator.js create mode 100644 js/src/tests/non262/Iterator/prototype/some/length.js create mode 100644 js/src/tests/non262/Iterator/prototype/some/name.js create mode 100644 js/src/tests/non262/Iterator/prototype/some/next-throws-iterator-not-closed.js create mode 100644 js/src/tests/non262/Iterator/prototype/some/proxy.js create mode 100644 js/src/tests/non262/Iterator/prototype/some/return-false-if-none-match.js create mode 100644 js/src/tests/non262/Iterator/prototype/some/short-circuit-on-true.js create mode 100644 js/src/tests/non262/Iterator/prototype/some/this-not-iterator-throws.js create mode 100644 js/src/tests/non262/Iterator/prototype/some/value-throws-iterator-not-closed.js create mode 100644 js/src/tests/non262/Iterator/prototype/take-drop-throw-eagerly-on-negative.js create mode 100644 js/src/tests/non262/Iterator/prototype/take-drop-throw-eagerly-on-non-integer.js create mode 100644 js/src/tests/non262/Iterator/prototype/take/close-iterator-when-none-remaining.js create mode 100644 js/src/tests/non262/Iterator/prototype/take/length.js create mode 100644 js/src/tests/non262/Iterator/prototype/take/name.js create mode 100644 js/src/tests/non262/Iterator/prototype/take/take-more-than-available.js create mode 100644 js/src/tests/non262/Iterator/prototype/take/take.js create mode 100644 js/src/tests/non262/Iterator/prototype/toArray/create-in-current-realm.js create mode 100644 js/src/tests/non262/Iterator/prototype/toArray/descriptor.js create mode 100644 js/src/tests/non262/Iterator/prototype/toArray/iterator-empty.js create mode 100644 js/src/tests/non262/Iterator/prototype/toArray/length.js create mode 100644 js/src/tests/non262/Iterator/prototype/toArray/name.js create mode 100644 js/src/tests/non262/Iterator/prototype/toArray/next-throws.js create mode 100644 js/src/tests/non262/Iterator/prototype/toArray/proxy.js create mode 100644 js/src/tests/non262/Iterator/prototype/toArray/this-not-iterator-throws.js create mode 100644 js/src/tests/non262/Iterator/prototype/toArray/toArray.js create mode 100644 js/src/tests/non262/Iterator/prototype/toArray/value-throws-iterator-not-closed.js create mode 100644 js/src/tests/non262/JSON/browser.js create mode 100644 js/src/tests/non262/JSON/cyclic-stringify-unrelated.js create mode 100644 js/src/tests/non262/JSON/cyclic-stringify.js create mode 100644 js/src/tests/non262/JSON/immutable-reviver.js create mode 100644 js/src/tests/non262/JSON/immutable.js create mode 100644 js/src/tests/non262/JSON/parse-arguments.js create mode 100644 js/src/tests/non262/JSON/parse-array-gc.js create mode 100644 js/src/tests/non262/JSON/parse-crockford-01.js create mode 100644 js/src/tests/non262/JSON/parse-mega-huge-array.js create mode 100644 js/src/tests/non262/JSON/parse-number-syntax.js create mode 100644 js/src/tests/non262/JSON/parse-octal-syntax-error.js create mode 100644 js/src/tests/non262/JSON/parse-primitives.js create mode 100644 js/src/tests/non262/JSON/parse-reviver-array-delete.js create mode 100644 js/src/tests/non262/JSON/parse-reviver.js create mode 100644 js/src/tests/non262/JSON/parse-syntax-errors-01.js create mode 100644 js/src/tests/non262/JSON/parse-syntax-errors-02.js create mode 100644 js/src/tests/non262/JSON/parse-syntax-errors-03.js create mode 100644 js/src/tests/non262/JSON/parse-with-source.js create mode 100644 js/src/tests/non262/JSON/parse.js create mode 100644 js/src/tests/non262/JSON/regress-458959.js create mode 100644 js/src/tests/non262/JSON/regress-459293.js create mode 100644 js/src/tests/non262/JSON/shell.js create mode 100644 js/src/tests/non262/JSON/small-codepoints.js create mode 100644 js/src/tests/non262/JSON/stringify-boxed-primitives.js create mode 100644 js/src/tests/non262/JSON/stringify-call-replacer-once.js create mode 100644 js/src/tests/non262/JSON/stringify-call-toJSON-once.js create mode 100644 js/src/tests/non262/JSON/stringify-dropping-elements.js create mode 100644 js/src/tests/non262/JSON/stringify-fastpath.js create mode 100644 js/src/tests/non262/JSON/stringify-gap.js create mode 100644 js/src/tests/non262/JSON/stringify-ignore-noncallable-toJSON.js create mode 100644 js/src/tests/non262/JSON/stringify-large-replacer-array.js create mode 100644 js/src/tests/non262/JSON/stringify-missing-arguments.js create mode 100644 js/src/tests/non262/JSON/stringify-nonarray-noncallable-replacer.js create mode 100644 js/src/tests/non262/JSON/stringify-primitives.js create mode 100644 js/src/tests/non262/JSON/stringify-replacer-array-boxed-elements.js create mode 100644 js/src/tests/non262/JSON/stringify-replacer-array-duplicated-element.js create mode 100644 js/src/tests/non262/JSON/stringify-replacer-array-edgecase-jsid-elements.js create mode 100644 js/src/tests/non262/JSON/stringify-replacer-array-hijinks.js create mode 100644 js/src/tests/non262/JSON/stringify-replacer-array-skipped-element.js create mode 100644 js/src/tests/non262/JSON/stringify-replacer-array-trailing-holes.js create mode 100644 js/src/tests/non262/JSON/stringify-replacer-with-array-indexes.js create mode 100644 js/src/tests/non262/JSON/stringify-replacer.js create mode 100644 js/src/tests/non262/JSON/stringify-special-escapes.js create mode 100644 js/src/tests/non262/JSON/stringify-toJSON-arguments.js create mode 100644 js/src/tests/non262/JSON/stringify.js create mode 100644 js/src/tests/non262/JSON/trailing-comma.js create mode 100644 js/src/tests/non262/Map/NaN-as-key.js create mode 100644 js/src/tests/non262/Map/browser.js create mode 100644 js/src/tests/non262/Map/constructor-iterator-close.js create mode 100644 js/src/tests/non262/Map/constructor-iterator-primitive.js create mode 100644 js/src/tests/non262/Map/forEach-selfhosted-behavior.js create mode 100644 js/src/tests/non262/Map/getter-name.js create mode 100644 js/src/tests/non262/Map/iterable.js create mode 100644 js/src/tests/non262/Map/iterator-thisv-error.js create mode 100644 js/src/tests/non262/Map/record-tuple.js create mode 100644 js/src/tests/non262/Map/shell.js create mode 100644 js/src/tests/non262/Map/symbols.js create mode 100644 js/src/tests/non262/Math/15.8.1.js create mode 100644 js/src/tests/non262/Math/15.8.2.13.js create mode 100644 js/src/tests/non262/Math/15.8.2.16.js create mode 100644 js/src/tests/non262/Math/15.8.2.17.js create mode 100644 js/src/tests/non262/Math/15.8.2.18.js create mode 100644 js/src/tests/non262/Math/15.8.2.2.js create mode 100644 js/src/tests/non262/Math/15.8.2.3.js create mode 100644 js/src/tests/non262/Math/15.8.2.4.js create mode 100644 js/src/tests/non262/Math/15.8.2.5.js create mode 100644 js/src/tests/non262/Math/15.8.2.7.js create mode 100644 js/src/tests/non262/Math/15.8.2.8.js create mode 100644 js/src/tests/non262/Math/20.2.2.ToNumber.js create mode 100644 js/src/tests/non262/Math/Pow.js create mode 100644 js/src/tests/non262/Math/acosh-approx.js create mode 100644 js/src/tests/non262/Math/acosh-exact.js create mode 100644 js/src/tests/non262/Math/asinh-approx.js create mode 100644 js/src/tests/non262/Math/asinh-exact.js create mode 100644 js/src/tests/non262/Math/atanh-approx.js create mode 100644 js/src/tests/non262/Math/atanh-exact.js create mode 100644 js/src/tests/non262/Math/browser.js create mode 100644 js/src/tests/non262/Math/cbrt-approx.js create mode 100644 js/src/tests/non262/Math/cbrt-exact.js create mode 100644 js/src/tests/non262/Math/clz32.js create mode 100644 js/src/tests/non262/Math/cosh-approx.js create mode 100644 js/src/tests/non262/Math/cosh-exact.js create mode 100644 js/src/tests/non262/Math/exp-exact.js create mode 100644 js/src/tests/non262/Math/expm1-approx.js create mode 100644 js/src/tests/non262/Math/expm1-exact.js create mode 100644 js/src/tests/non262/Math/expm1-monotonicity.js create mode 100644 js/src/tests/non262/Math/fround.js create mode 100644 js/src/tests/non262/Math/log10-approx.js create mode 100644 js/src/tests/non262/Math/log10-exact.js create mode 100644 js/src/tests/non262/Math/log1p-approx.js create mode 100644 js/src/tests/non262/Math/log1p-exact.js create mode 100644 js/src/tests/non262/Math/log2-approx.js create mode 100644 js/src/tests/non262/Math/log2-exact.js create mode 100644 js/src/tests/non262/Math/pow-approx-pow10.js create mode 100644 js/src/tests/non262/Math/pow-approx.js create mode 100644 js/src/tests/non262/Math/shell.js create mode 100644 js/src/tests/non262/Math/sign.js create mode 100644 js/src/tests/non262/Math/sinh-approx.js create mode 100644 js/src/tests/non262/Math/sinh-exact.js create mode 100644 js/src/tests/non262/Math/tanh-approx.js create mode 100644 js/src/tests/non262/Math/tanh-exact.js create mode 100644 js/src/tests/non262/Math/trunc.js create mode 100644 js/src/tests/non262/Number/0x-without-following-hexdigits.js create mode 100644 js/src/tests/non262/Number/15.7.3.7-EPSILON.js create mode 100644 js/src/tests/non262/Number/15.7.4.2.js create mode 100644 js/src/tests/non262/Number/20.1.2.10-MIN_SAFE_INTEGER.js create mode 100644 js/src/tests/non262/Number/20.1.2.6-MAX_SAFE_INTEGER.js create mode 100644 js/src/tests/non262/Number/20.1.3.2-toExponential.js create mode 100644 js/src/tests/non262/Number/20.1.3.2-toPrecision.js create mode 100644 js/src/tests/non262/Number/20.1.3.3-toFixed.js create mode 100644 js/src/tests/non262/Number/ToNumber.js create mode 100644 js/src/tests/non262/Number/browser.js create mode 100644 js/src/tests/non262/Number/conversion-invalid-precision.js create mode 100644 js/src/tests/non262/Number/defaultvalue.js create mode 100644 js/src/tests/non262/Number/isSafeInteger-01.js create mode 100644 js/src/tests/non262/Number/numericSeparator.js create mode 100644 js/src/tests/non262/Number/parseFloat-01.js create mode 100644 js/src/tests/non262/Number/parseInt-01.js create mode 100644 js/src/tests/non262/Number/parseInt-default-to-decimal.js create mode 100644 js/src/tests/non262/Number/regress-442242-01.js create mode 100644 js/src/tests/non262/Number/shell.js create mode 100644 js/src/tests/non262/Number/toExponential-values.js create mode 100644 js/src/tests/non262/Number/toFixed-values.js create mode 100644 js/src/tests/non262/Number/toPrecision-values.js create mode 100644 js/src/tests/non262/Number/toString-radix-handling.js create mode 100644 js/src/tests/non262/Number/tonumber-string-hex.js create mode 100644 js/src/tests/non262/PrivateName/browser.js create mode 100644 js/src/tests/non262/PrivateName/constructor-args.js create mode 100644 js/src/tests/non262/PrivateName/error-locations.js create mode 100644 js/src/tests/non262/PrivateName/error-outside-class.js create mode 100644 js/src/tests/non262/PrivateName/home-object-when-preceded-by-computed-key.js create mode 100644 js/src/tests/non262/PrivateName/illegal-delete.js create mode 100644 js/src/tests/non262/PrivateName/illegal-in-class-context.js create mode 100644 js/src/tests/non262/PrivateName/illegal-in-identifier-context.js create mode 100644 js/src/tests/non262/PrivateName/illegal-in-object-context.js create mode 100644 js/src/tests/non262/PrivateName/lexical-presence.js create mode 100644 js/src/tests/non262/PrivateName/modify-non-extensible.js create mode 100644 js/src/tests/non262/PrivateName/names.js create mode 100644 js/src/tests/non262/PrivateName/nested-class-name-used.js create mode 100644 js/src/tests/non262/PrivateName/not-iterable.js create mode 100644 js/src/tests/non262/PrivateName/parse-utf8-non-ascii-identifier.js create mode 100644 js/src/tests/non262/PrivateName/prototype-proxy.js create mode 100644 js/src/tests/non262/PrivateName/proxy-1.js create mode 100644 js/src/tests/non262/PrivateName/proxy-ccw.js create mode 100644 js/src/tests/non262/PrivateName/proxy-init-set.js create mode 100644 js/src/tests/non262/PrivateName/read-private-eval.js create mode 100644 js/src/tests/non262/PrivateName/shell.js create mode 100644 js/src/tests/non262/PrivateName/unicode-names.js create mode 100644 js/src/tests/non262/Promise/allSettled.js create mode 100644 js/src/tests/non262/Promise/any-stack-overflow.js create mode 100644 js/src/tests/non262/Promise/any-stack.js create mode 100644 js/src/tests/non262/Promise/any.js create mode 100644 js/src/tests/non262/Promise/browser.js create mode 100644 js/src/tests/non262/Promise/bug-1287334.js create mode 100644 js/src/tests/non262/Promise/bug-1288382.js create mode 100644 js/src/tests/non262/Promise/bug-1289040.js create mode 100644 js/src/tests/non262/Promise/bug-1792196.js create mode 100644 js/src/tests/non262/Promise/dependent-promises.js create mode 100644 js/src/tests/non262/Promise/enqueue-promise-reactions.js create mode 100644 js/src/tests/non262/Promise/for-of-iterator-uses-getv.js create mode 100644 js/src/tests/non262/Promise/get-wait-for-all-promise.js create mode 100644 js/src/tests/non262/Promise/iterator-close.js create mode 100644 js/src/tests/non262/Promise/iterator-primitive.js create mode 100644 js/src/tests/non262/Promise/methods-non-enumerable.js create mode 100644 js/src/tests/non262/Promise/promise-all.js create mode 100644 js/src/tests/non262/Promise/promise-basics.js create mode 100644 js/src/tests/non262/Promise/promise-rejection-tracking-optimized.js create mode 100644 js/src/tests/non262/Promise/promise-rejection-tracking.js create mode 100644 js/src/tests/non262/Promise/promise-species.js create mode 100644 js/src/tests/non262/Promise/promise-subclassing.js create mode 100644 js/src/tests/non262/Promise/self-resolve.js create mode 100644 js/src/tests/non262/Promise/shell.js create mode 100644 js/src/tests/non262/Promise/withResolvers.js create mode 100644 js/src/tests/non262/Proxy/browser.js create mode 100644 js/src/tests/non262/Proxy/define-writable-as-non-writable.js create mode 100644 js/src/tests/non262/Proxy/delete-non-extensible.js create mode 100644 js/src/tests/non262/Proxy/getPrototypeOf.js create mode 100644 js/src/tests/non262/Proxy/global-receiver.js create mode 100644 js/src/tests/non262/Proxy/hasInstance.js create mode 100644 js/src/tests/non262/Proxy/json-stringify-replacer-array-revocable-proxy.js create mode 100644 js/src/tests/non262/Proxy/ownkeys-allowed-types.js create mode 100644 js/src/tests/non262/Proxy/ownkeys-linear.js create mode 100644 js/src/tests/non262/Proxy/ownkeys-trap-duplicates.js create mode 100644 js/src/tests/non262/Proxy/proxy-__proto__.js create mode 100644 js/src/tests/non262/Proxy/proxy-constructNonObject.js create mode 100644 js/src/tests/non262/Proxy/proxy-for-in.js create mode 100644 js/src/tests/non262/Proxy/proxy-no-receiver-overwrite.js create mode 100644 js/src/tests/non262/Proxy/proxy-proto-lazy-props.js create mode 100644 js/src/tests/non262/Proxy/proxy-with-revoked-arguments.js create mode 100644 js/src/tests/non262/Proxy/regress-bug1037770.js create mode 100644 js/src/tests/non262/Proxy/regress-bug1062349.js create mode 100644 js/src/tests/non262/Proxy/regress-bug950407.js create mode 100644 js/src/tests/non262/Proxy/report-writable-as-non-writable.js create mode 100644 js/src/tests/non262/Proxy/revocable-proxy-prototype.js create mode 100644 js/src/tests/non262/Proxy/revoke-as-side-effect.js create mode 100644 js/src/tests/non262/Proxy/revoke-no-name.js create mode 100644 js/src/tests/non262/Proxy/revoked-get-function-realm-typeerror.js create mode 100644 js/src/tests/non262/Proxy/setPrototypeOf.js create mode 100644 js/src/tests/non262/Proxy/shell.js create mode 100644 js/src/tests/non262/Proxy/trap-null.js create mode 100644 js/src/tests/non262/ReadableStream/basic-pull.js create mode 100644 js/src/tests/non262/ReadableStream/basic-push.js create mode 100644 js/src/tests/non262/ReadableStream/bug-1501502.js create mode 100644 js/src/tests/non262/ReadableStream/bug-1549768.js create mode 100644 js/src/tests/non262/ReadableStream/closed-is-handled.js create mode 100644 js/src/tests/non262/ReadableStream/constructor-default.js create mode 100644 js/src/tests/non262/ReadableStream/readable-stream-globals.js create mode 100644 js/src/tests/non262/ReadableStream/shell.js create mode 100644 js/src/tests/non262/ReadableStream/subclassing.js create mode 100644 js/src/tests/non262/ReadableStream/tee-start.js create mode 100644 js/src/tests/non262/Record/browser.js create mode 100644 js/src/tests/non262/Record/constructor.js create mode 100644 js/src/tests/non262/Record/cross-realm.js create mode 100644 js/src/tests/non262/Record/enumeration.js create mode 100644 js/src/tests/non262/Record/equality.js create mode 100644 js/src/tests/non262/Record/json.js create mode 100644 js/src/tests/non262/Record/literal.js create mode 100644 js/src/tests/non262/Record/properties.js create mode 100644 js/src/tests/non262/Record/property-descriptors.js create mode 100644 js/src/tests/non262/Record/shell.js create mode 100644 js/src/tests/non262/Record/syntax.js create mode 100644 js/src/tests/non262/Record/wrapper.js create mode 100644 js/src/tests/non262/Reflect/apply.js create mode 100644 js/src/tests/non262/Reflect/argumentsList.js create mode 100644 js/src/tests/non262/Reflect/browser.js create mode 100644 js/src/tests/non262/Reflect/construct.js create mode 100644 js/src/tests/non262/Reflect/defineProperty.js create mode 100644 js/src/tests/non262/Reflect/deleteProperty.js create mode 100644 js/src/tests/non262/Reflect/get.js create mode 100644 js/src/tests/non262/Reflect/getOwnPropertyDescriptor.js create mode 100644 js/src/tests/non262/Reflect/getPrototypeOf.js create mode 100644 js/src/tests/non262/Reflect/has.js create mode 100644 js/src/tests/non262/Reflect/isExtensible.js create mode 100644 js/src/tests/non262/Reflect/ownKeys.js create mode 100644 js/src/tests/non262/Reflect/preventExtensions.js create mode 100644 js/src/tests/non262/Reflect/propertyKeys.js create mode 100644 js/src/tests/non262/Reflect/set.js create mode 100644 js/src/tests/non262/Reflect/setPrototypeOf.js create mode 100644 js/src/tests/non262/Reflect/shell.js create mode 100644 js/src/tests/non262/Reflect/surfaces.js create mode 100644 js/src/tests/non262/Reflect/target.js create mode 100644 js/src/tests/non262/RegExp/15.10.5-01.js create mode 100644 js/src/tests/non262/RegExp/15.10.6.2-2.js create mode 100644 js/src/tests/non262/RegExp/15.10.7.5-01.js create mode 100644 js/src/tests/non262/RegExp/15.5.4.11.js create mode 100644 js/src/tests/non262/RegExp/7.8.5-01.js create mode 100644 js/src/tests/non262/RegExp/RegExpExec-exec-type-check.js create mode 100644 js/src/tests/non262/RegExp/RegExpExec-exec.js create mode 100644 js/src/tests/non262/RegExp/RegExpExec-return.js create mode 100644 js/src/tests/non262/RegExp/RegExp_dollar_number.js create mode 100644 js/src/tests/non262/RegExp/RegExp_lastMatch.js create mode 100644 js/src/tests/non262/RegExp/RegExp_lastMatch_as_array.js create mode 100644 js/src/tests/non262/RegExp/RegExp_lastParen.js create mode 100644 js/src/tests/non262/RegExp/RegExp_lastParen_as_array.js create mode 100644 js/src/tests/non262/RegExp/RegExp_leftContext.js create mode 100644 js/src/tests/non262/RegExp/RegExp_leftContext_as_array.js create mode 100644 js/src/tests/non262/RegExp/RegExp_object.js create mode 100644 js/src/tests/non262/RegExp/RegExp_rightContext.js create mode 100644 js/src/tests/non262/RegExp/RegExp_rightContext_as_array.js create mode 100644 js/src/tests/non262/RegExp/browser.js create mode 100644 js/src/tests/non262/RegExp/character-class-escape-s.js create mode 100644 js/src/tests/non262/RegExp/character-escape-class-s-mongolian-vowel-separator.js create mode 100644 js/src/tests/non262/RegExp/class-null.js create mode 100644 js/src/tests/non262/RegExp/compile-lastIndex.js create mode 100644 js/src/tests/non262/RegExp/compile-symbol.js create mode 100644 js/src/tests/non262/RegExp/constructor-IsRegExp.js create mode 100644 js/src/tests/non262/RegExp/constructor-constructor.js create mode 100644 js/src/tests/non262/RegExp/constructor-ordering-2.js create mode 100644 js/src/tests/non262/RegExp/constructor-ordering.js create mode 100644 js/src/tests/non262/RegExp/constructor-regexp-unicode.js create mode 100644 js/src/tests/non262/RegExp/constructor-regexp.js create mode 100644 js/src/tests/non262/RegExp/constructor-symbol.js create mode 100644 js/src/tests/non262/RegExp/control_characters.js create mode 100644 js/src/tests/non262/RegExp/cross-compartment-getter.js create mode 100644 js/src/tests/non262/RegExp/descriptor.js create mode 100644 js/src/tests/non262/RegExp/empty-lookahead.js create mode 100644 js/src/tests/non262/RegExp/escape.js create mode 100644 js/src/tests/non262/RegExp/everything.js create mode 100644 js/src/tests/non262/RegExp/exec-002.js create mode 100644 js/src/tests/non262/RegExp/exec-lastIndex-ToInteger.js create mode 100644 js/src/tests/non262/RegExp/exec-lastIndex-negative.js create mode 100644 js/src/tests/non262/RegExp/exec.js create mode 100644 js/src/tests/non262/RegExp/flag-accessors.js create mode 100644 js/src/tests/non262/RegExp/flags-param-handling.js create mode 100644 js/src/tests/non262/RegExp/flags.js create mode 100644 js/src/tests/non262/RegExp/getter-name.js create mode 100644 js/src/tests/non262/RegExp/ignoreCase-multiple.js create mode 100644 js/src/tests/non262/RegExp/ignoreCase-non-latin1-to-latin1.js create mode 100644 js/src/tests/non262/RegExp/instance-property-storage-introspection.js create mode 100644 js/src/tests/non262/RegExp/lastIndex-exec.js create mode 100644 js/src/tests/non262/RegExp/lastIndex-match-or-replace.js create mode 100644 js/src/tests/non262/RegExp/lastIndex-nonwritable.js create mode 100644 js/src/tests/non262/RegExp/lastIndex-search.js create mode 100644 js/src/tests/non262/RegExp/match-local-tolength-recompilation.js create mode 100644 js/src/tests/non262/RegExp/match-this.js create mode 100644 js/src/tests/non262/RegExp/match-trace.js create mode 100644 js/src/tests/non262/RegExp/match.js create mode 100644 js/src/tests/non262/RegExp/multiline-001.js create mode 100644 js/src/tests/non262/RegExp/octal-001.js create mode 100644 js/src/tests/non262/RegExp/octal-002.js create mode 100644 js/src/tests/non262/RegExp/octal-003.js create mode 100644 js/src/tests/non262/RegExp/oom-in-construction.js create mode 100644 js/src/tests/non262/RegExp/perlstress-001.js create mode 100644 js/src/tests/non262/RegExp/perlstress-002.js create mode 100644 js/src/tests/non262/RegExp/properties-001.js create mode 100644 js/src/tests/non262/RegExp/properties-002.js create mode 100644 js/src/tests/non262/RegExp/prototype-different-global.js create mode 100644 js/src/tests/non262/RegExp/prototype.js create mode 100644 js/src/tests/non262/RegExp/regexp-enumerate-001.js create mode 100644 js/src/tests/non262/RegExp/regexp-space-character-class.js create mode 100644 js/src/tests/non262/RegExp/regress-001.js create mode 100644 js/src/tests/non262/RegExp/regress-100199.js create mode 100644 js/src/tests/non262/RegExp/regress-105972.js create mode 100644 js/src/tests/non262/RegExp/regress-119909.js create mode 100644 js/src/tests/non262/RegExp/regress-122076.js create mode 100644 js/src/tests/non262/RegExp/regress-123437.js create mode 100644 js/src/tests/non262/RegExp/regress-165353.js create mode 100644 js/src/tests/non262/RegExp/regress-169497.js create mode 100644 js/src/tests/non262/RegExp/regress-169534.js create mode 100644 js/src/tests/non262/RegExp/regress-187133.js create mode 100644 js/src/tests/non262/RegExp/regress-188206.js create mode 100644 js/src/tests/non262/RegExp/regress-191479.js create mode 100644 js/src/tests/non262/RegExp/regress-202564.js create mode 100644 js/src/tests/non262/RegExp/regress-209067.js create mode 100644 js/src/tests/non262/RegExp/regress-209919.js create mode 100644 js/src/tests/non262/RegExp/regress-216591.js create mode 100644 js/src/tests/non262/RegExp/regress-220367-001.js create mode 100644 js/src/tests/non262/RegExp/regress-223273.js create mode 100644 js/src/tests/non262/RegExp/regress-223535.js create mode 100644 js/src/tests/non262/RegExp/regress-224676.js create mode 100644 js/src/tests/non262/RegExp/regress-225289.js create mode 100644 js/src/tests/non262/RegExp/regress-225343.js create mode 100644 js/src/tests/non262/RegExp/regress-24712.js create mode 100644 js/src/tests/non262/RegExp/regress-285219.js create mode 100644 js/src/tests/non262/RegExp/regress-28686.js create mode 100644 js/src/tests/non262/RegExp/regress-305064.js create mode 100644 js/src/tests/non262/RegExp/regress-309840.js create mode 100644 js/src/tests/non262/RegExp/regress-312351.js create mode 100644 js/src/tests/non262/RegExp/regress-31316.js create mode 100644 js/src/tests/non262/RegExp/regress-334158.js create mode 100644 js/src/tests/non262/RegExp/regress-346090.js create mode 100644 js/src/tests/non262/RegExp/regress-367888.js create mode 100644 js/src/tests/non262/RegExp/regress-375642.js create mode 100644 js/src/tests/non262/RegExp/regress-375651.js create mode 100644 js/src/tests/non262/RegExp/regress-375711.js create mode 100644 js/src/tests/non262/RegExp/regress-375715-01-n.js create mode 100644 js/src/tests/non262/RegExp/regress-375715-02.js create mode 100644 js/src/tests/non262/RegExp/regress-375715-03.js create mode 100644 js/src/tests/non262/RegExp/regress-375715-04.js create mode 100644 js/src/tests/non262/RegExp/regress-429241.js create mode 100644 js/src/tests/non262/RegExp/regress-436700.js create mode 100644 js/src/tests/non262/RegExp/regress-465862.js create mode 100644 js/src/tests/non262/RegExp/regress-57572.js create mode 100644 js/src/tests/non262/RegExp/regress-57631.js create mode 100644 js/src/tests/non262/RegExp/regress-576828.js create mode 100644 js/src/tests/non262/RegExp/regress-613820-1.js create mode 100644 js/src/tests/non262/RegExp/regress-613820-2.js create mode 100644 js/src/tests/non262/RegExp/regress-613820-3.js create mode 100644 js/src/tests/non262/RegExp/regress-617935.js create mode 100644 js/src/tests/non262/RegExp/regress-6359.js create mode 100644 js/src/tests/non262/RegExp/regress-67773.js create mode 100644 js/src/tests/non262/RegExp/regress-72964.js create mode 100644 js/src/tests/non262/RegExp/regress-76683.js create mode 100644 js/src/tests/non262/RegExp/regress-78156.js create mode 100644 js/src/tests/non262/RegExp/regress-87231.js create mode 100644 js/src/tests/non262/RegExp/regress-9141.js create mode 100644 js/src/tests/non262/RegExp/regress-98306.js create mode 100644 js/src/tests/non262/RegExp/regress-yarr-regexp.js create mode 100644 js/src/tests/non262/RegExp/replace-compile-elembase.js create mode 100644 js/src/tests/non262/RegExp/replace-compile.js create mode 100644 js/src/tests/non262/RegExp/replace-global-unicode.js create mode 100644 js/src/tests/non262/RegExp/replace-local-tolength-lastindex.js create mode 100644 js/src/tests/non262/RegExp/replace-local-tolength-recompilation.js create mode 100644 js/src/tests/non262/RegExp/replace-sticky-lastIndex.js create mode 100644 js/src/tests/non262/RegExp/replace-sticky.js create mode 100644 js/src/tests/non262/RegExp/replace-this.js create mode 100644 js/src/tests/non262/RegExp/replace-trace.js create mode 100644 js/src/tests/non262/RegExp/replace-twoBytes.js create mode 100644 js/src/tests/non262/RegExp/replace.js create mode 100644 js/src/tests/non262/RegExp/search-this.js create mode 100644 js/src/tests/non262/RegExp/search-trace.js create mode 100644 js/src/tests/non262/RegExp/search.js create mode 100644 js/src/tests/non262/RegExp/shell.js create mode 100644 js/src/tests/non262/RegExp/source.js create mode 100644 js/src/tests/non262/RegExp/split-deleted-flags.js create mode 100644 js/src/tests/non262/RegExp/split-flags-on-obj.js create mode 100644 js/src/tests/non262/RegExp/split-invalid-lastIndex.js create mode 100644 js/src/tests/non262/RegExp/split-limit.js create mode 100644 js/src/tests/non262/RegExp/split-obj.js create mode 100644 js/src/tests/non262/RegExp/split-prop-access.js create mode 100644 js/src/tests/non262/RegExp/split-this.js create mode 100644 js/src/tests/non262/RegExp/split-trace.js create mode 100644 js/src/tests/non262/RegExp/split.js create mode 100644 js/src/tests/non262/RegExp/sticky.js create mode 100644 js/src/tests/non262/RegExp/test-emptyMatch.js create mode 100644 js/src/tests/non262/RegExp/test-trailing.js create mode 100644 js/src/tests/non262/RegExp/toString.js create mode 100644 js/src/tests/non262/RegExp/unicode-back-reference.js create mode 100644 js/src/tests/non262/RegExp/unicode-braced.js create mode 100644 js/src/tests/non262/RegExp/unicode-character-class-escape.js create mode 100644 js/src/tests/non262/RegExp/unicode-class-braced.js create mode 100644 js/src/tests/non262/RegExp/unicode-class-empty.js create mode 100644 js/src/tests/non262/RegExp/unicode-class-ignoreCase.js create mode 100644 js/src/tests/non262/RegExp/unicode-class-lead-trail.js create mode 100644 js/src/tests/non262/RegExp/unicode-class-negated.js create mode 100644 js/src/tests/non262/RegExp/unicode-class-range.js create mode 100644 js/src/tests/non262/RegExp/unicode-class-raw.js create mode 100644 js/src/tests/non262/RegExp/unicode-disallow-extended.js create mode 100644 js/src/tests/non262/RegExp/unicode-everything.js create mode 100644 js/src/tests/non262/RegExp/unicode-ignoreCase-ascii.js create mode 100644 js/src/tests/non262/RegExp/unicode-ignoreCase-escape.js create mode 100644 js/src/tests/non262/RegExp/unicode-ignoreCase-negated.js create mode 100644 js/src/tests/non262/RegExp/unicode-ignoreCase-word-boundary.js create mode 100644 js/src/tests/non262/RegExp/unicode-ignoreCase.js create mode 100644 js/src/tests/non262/RegExp/unicode-index.js create mode 100644 js/src/tests/non262/RegExp/unicode-lead-trail.js create mode 100644 js/src/tests/non262/RegExp/unicode-raw.js create mode 100644 js/src/tests/non262/RegExp/yflag.js create mode 100644 js/src/tests/non262/Scope/browser.js create mode 100644 js/src/tests/non262/Scope/regress-154693.js create mode 100644 js/src/tests/non262/Scope/regress-181834.js create mode 100644 js/src/tests/non262/Scope/regress-184107.js create mode 100644 js/src/tests/non262/Scope/regress-185485.js create mode 100644 js/src/tests/non262/Scope/regress-191276.js create mode 100644 js/src/tests/non262/Scope/regress-192226.js create mode 100644 js/src/tests/non262/Scope/regress-202678-001.js create mode 100644 js/src/tests/non262/Scope/regress-202678-002.js create mode 100644 js/src/tests/non262/Scope/regress-208496-001.js create mode 100644 js/src/tests/non262/Scope/regress-208496-002.js create mode 100644 js/src/tests/non262/Scope/regress-220362.js create mode 100644 js/src/tests/non262/Scope/regress-446026-01.js create mode 100644 js/src/tests/non262/Scope/regress-446026-02.js create mode 100644 js/src/tests/non262/Scope/regress-77578-001.js create mode 100644 js/src/tests/non262/Scope/scope-002.js create mode 100644 js/src/tests/non262/Scope/scope-003.js create mode 100644 js/src/tests/non262/Scope/scope-004.js create mode 100644 js/src/tests/non262/Scope/shell.js create mode 100644 js/src/tests/non262/Script/browser.js create mode 100644 js/src/tests/non262/Script/delete-001.js create mode 100644 js/src/tests/non262/Script/function-002.js create mode 100644 js/src/tests/non262/Script/in-001.js create mode 100644 js/src/tests/non262/Script/new-001.js create mode 100644 js/src/tests/non262/Script/shell.js create mode 100644 js/src/tests/non262/Script/switch-001.js create mode 100644 js/src/tests/non262/Set/browser.js create mode 100644 js/src/tests/non262/Set/difference.js create mode 100644 js/src/tests/non262/Set/intersection.js create mode 100644 js/src/tests/non262/Set/is-disjoint-from.js create mode 100644 js/src/tests/non262/Set/is-subset-of.js create mode 100644 js/src/tests/non262/Set/is-superset-of.js create mode 100644 js/src/tests/non262/Set/shell.js create mode 100644 js/src/tests/non262/Set/symmetric-difference.js create mode 100644 js/src/tests/non262/Set/union.js create mode 100644 js/src/tests/non262/ShadowRealms/ccw-2.js create mode 100644 js/src/tests/non262/ShadowRealms/ccw.js create mode 100644 js/src/tests/non262/ShadowRealms/error.js create mode 100644 js/src/tests/non262/ShadowRealms/function-copy-name-and-length-fails-error-realm.js create mode 100644 js/src/tests/non262/ShadowRealms/function-return.js create mode 100644 js/src/tests/non262/ShadowRealms/interrupt-request.js create mode 100644 js/src/tests/non262/ShadowRealms/syntax-error.js create mode 100644 js/src/tests/non262/ShadowRealms/unwrap-wrap-with-proto.js create mode 100644 js/src/tests/non262/String/15.5.4.11-01.js create mode 100644 js/src/tests/non262/String/15.5.4.2.js create mode 100644 js/src/tests/non262/String/15.5.4.7.js create mode 100644 js/src/tests/non262/String/AdvanceStringIndex.js create mode 100644 js/src/tests/non262/String/IsRegExp.js create mode 100644 js/src/tests/non262/String/at.js create mode 100644 js/src/tests/non262/String/browser.js create mode 100644 js/src/tests/non262/String/codePointAt.js create mode 100644 js/src/tests/non262/String/defaultvalue.js create mode 100644 js/src/tests/non262/String/fromCodePoint.js create mode 100644 js/src/tests/non262/String/internalUsage.js create mode 100644 js/src/tests/non262/String/iterator_edge_cases.js create mode 100644 js/src/tests/non262/String/lastIndexOf-ToNumber-when-searchStr-larger-than-string.js create mode 100644 js/src/tests/non262/String/make-normalize-generateddata-input.py create mode 100644 js/src/tests/non262/String/match-001.js create mode 100644 js/src/tests/non262/String/match-002.js create mode 100644 js/src/tests/non262/String/match-003.js create mode 100644 js/src/tests/non262/String/match-004.js create mode 100644 js/src/tests/non262/String/match-GetMethod.js create mode 100644 js/src/tests/non262/String/match-defines-match-elements.js create mode 100644 js/src/tests/non262/String/match-forward-lookahead.js create mode 100644 js/src/tests/non262/String/match-throws-nonwritable-lastIndex-global.js create mode 100644 js/src/tests/non262/String/match-updates-global-lastIndex.js create mode 100644 js/src/tests/non262/String/match.js create mode 100644 js/src/tests/non262/String/matchAll.js create mode 100644 js/src/tests/non262/String/normalize-form-non-atom.js create mode 100644 js/src/tests/non262/String/normalize-generateddata-input.js create mode 100644 js/src/tests/non262/String/normalize-generateddata-part0.js create mode 100644 js/src/tests/non262/String/normalize-generateddata-part1-not-listed.js create mode 100644 js/src/tests/non262/String/normalize-generateddata-part1.js create mode 100644 js/src/tests/non262/String/normalize-generateddata-part2.js create mode 100644 js/src/tests/non262/String/normalize-generateddata-part3.js create mode 100644 js/src/tests/non262/String/normalize-generic.js create mode 100644 js/src/tests/non262/String/normalize-parameter.js create mode 100644 js/src/tests/non262/String/normalize-rope.js create mode 100644 js/src/tests/non262/String/raw.js create mode 100644 js/src/tests/non262/String/regress-104375.js create mode 100644 js/src/tests/non262/String/regress-107771.js create mode 100644 js/src/tests/non262/String/regress-112626.js create mode 100644 js/src/tests/non262/String/regress-179068.js create mode 100644 js/src/tests/non262/String/regress-189898.js create mode 100644 js/src/tests/non262/String/regress-304376.js create mode 100644 js/src/tests/non262/String/regress-305064.js create mode 100644 js/src/tests/non262/String/regress-313567.js create mode 100644 js/src/tests/non262/String/regress-369778.js create mode 100644 js/src/tests/non262/String/regress-392378.js create mode 100644 js/src/tests/non262/String/regress-83293.js create mode 100644 js/src/tests/non262/String/replace-GetMethod.js create mode 100644 js/src/tests/non262/String/replace-bad-dollar-single-quote.js create mode 100644 js/src/tests/non262/String/replace-flags.js create mode 100644 js/src/tests/non262/String/replace-math.js create mode 100644 js/src/tests/non262/String/replace-rope-empty.js create mode 100644 js/src/tests/non262/String/replace-throws-nonwritable-lastIndex-global.js create mode 100644 js/src/tests/non262/String/replace-updates-global-lastIndex.js create mode 100644 js/src/tests/non262/String/replace.js create mode 100644 js/src/tests/non262/String/replaceAll.js create mode 100644 js/src/tests/non262/String/ropes.js create mode 100644 js/src/tests/non262/String/search-GetMethod.js create mode 100644 js/src/tests/non262/String/search.js create mode 100644 js/src/tests/non262/String/shell.js create mode 100644 js/src/tests/non262/String/split-01.js create mode 100644 js/src/tests/non262/String/split-GetMethod.js create mode 100644 js/src/tests/non262/String/split-order.js create mode 100644 js/src/tests/non262/String/split-undefined-separator.js create mode 100644 js/src/tests/non262/String/split-xregexp.js create mode 100644 js/src/tests/non262/String/split.js create mode 100644 js/src/tests/non262/String/string-code-point-upper-lower-mapping.js create mode 100644 js/src/tests/non262/String/string-object-length.js create mode 100644 js/src/tests/non262/String/string-pad-start-end.js create mode 100644 js/src/tests/non262/String/string-space-trim.js create mode 100644 js/src/tests/non262/String/string-upper-lower-mapping.js create mode 100644 js/src/tests/non262/String/thisv-error.js create mode 100644 js/src/tests/non262/String/two-length-nonlatin-indexOf.js create mode 100644 js/src/tests/non262/String/unicode-braced.js create mode 100644 js/src/tests/non262/String/utf8-encode.js create mode 100644 js/src/tests/non262/String/well-formed.js create mode 100644 js/src/tests/non262/Symbol/as-base-value.js create mode 100644 js/src/tests/non262/Symbol/browser.js create mode 100644 js/src/tests/non262/Symbol/comparisons.js create mode 100644 js/src/tests/non262/Symbol/constructor.js create mode 100644 js/src/tests/non262/Symbol/conversions.js create mode 100644 js/src/tests/non262/Symbol/enumeration-order.js create mode 100644 js/src/tests/non262/Symbol/enumeration.js create mode 100644 js/src/tests/non262/Symbol/equality.js create mode 100644 js/src/tests/non262/Symbol/errors.js create mode 100644 js/src/tests/non262/Symbol/for-in-order.js create mode 100644 js/src/tests/non262/Symbol/for.js create mode 100644 js/src/tests/non262/Symbol/json-stringify-keys.js create mode 100644 js/src/tests/non262/Symbol/json-stringify-values.js create mode 100644 js/src/tests/non262/Symbol/keyFor.js create mode 100644 js/src/tests/non262/Symbol/property-accessor.js create mode 100644 js/src/tests/non262/Symbol/property-basics.js create mode 100644 js/src/tests/non262/Symbol/property-inheritance.js create mode 100644 js/src/tests/non262/Symbol/property-nonwritable.js create mode 100644 js/src/tests/non262/Symbol/property-reflection.js create mode 100644 js/src/tests/non262/Symbol/realms.js create mode 100644 js/src/tests/non262/Symbol/shell.js create mode 100644 js/src/tests/non262/Symbol/species.js create mode 100644 js/src/tests/non262/Symbol/surfaces.js create mode 100644 js/src/tests/non262/Symbol/symbol-object-not-unboxed-for-value-to-id.js create mode 100644 js/src/tests/non262/Symbol/toPrimitive-undefined-or-null.js create mode 100644 js/src/tests/non262/Symbol/toPrimitive.js create mode 100644 js/src/tests/non262/Symbol/toString.js create mode 100644 js/src/tests/non262/Symbol/toStringTag.js create mode 100644 js/src/tests/non262/Symbol/typed-arrays.js create mode 100644 js/src/tests/non262/Symbol/typeof.js create mode 100644 js/src/tests/non262/Symbol/valueOf.js create mode 100644 js/src/tests/non262/Symbol/well-known.js create mode 100644 js/src/tests/non262/Temporal/TimeZone/browser.js create mode 100644 js/src/tests/non262/Temporal/TimeZone/getPossibleInstantsFor-returns-dead-proxy.js create mode 100644 js/src/tests/non262/Temporal/TimeZone/shell.js create mode 100644 js/src/tests/non262/Temporal/browser.js create mode 100644 js/src/tests/non262/Temporal/shell.js create mode 100644 js/src/tests/non262/Tuple/4.1.2.11.js create mode 100644 js/src/tests/non262/Tuple/4.1.2.6.js create mode 100644 js/src/tests/non262/Tuple/9.1.1.1.js create mode 100644 js/src/tests/non262/Tuple/browser.js create mode 100644 js/src/tests/non262/Tuple/constructor.js create mode 100644 js/src/tests/non262/Tuple/constructor/8.2.1.js create mode 100644 js/src/tests/non262/Tuple/constructor/8.2.2.js create mode 100644 js/src/tests/non262/Tuple/constructor/call-method.js create mode 100644 js/src/tests/non262/Tuple/constructor/is-a-constructor.js create mode 100644 js/src/tests/non262/Tuple/constructor/length.js create mode 100644 js/src/tests/non262/Tuple/constructor/name.js create mode 100644 js/src/tests/non262/Tuple/cross-realm.js create mode 100644 js/src/tests/non262/Tuple/elements-literal.js create mode 100644 js/src/tests/non262/Tuple/elements.js create mode 100644 js/src/tests/non262/Tuple/enumeration.js create mode 100644 js/src/tests/non262/Tuple/equality.js create mode 100644 js/src/tests/non262/Tuple/from/arraylike-get-length-error.js create mode 100644 js/src/tests/non262/Tuple/from/arraylike-to-length-error.js create mode 100644 js/src/tests/non262/Tuple/from/calling-from-valid-1-noStrict.js create mode 100644 js/src/tests/non262/Tuple/from/calling-from-valid-1-onlyStrict-strict.js create mode 100644 js/src/tests/non262/Tuple/from/calling-from-valid-2.js create mode 100644 js/src/tests/non262/Tuple/from/descriptor.js create mode 100644 js/src/tests/non262/Tuple/from/elements-added-after.js create mode 100644 js/src/tests/non262/Tuple/from/elements-deleted-after.js create mode 100644 js/src/tests/non262/Tuple/from/from.js create mode 100644 js/src/tests/non262/Tuple/from/get-iter-method-err.js create mode 100644 js/src/tests/non262/Tuple/from/indexed-setters.js create mode 100644 js/src/tests/non262/Tuple/from/items-is-arraybuffer.js create mode 100644 js/src/tests/non262/Tuple/from/items-is-null-throws.js create mode 100644 js/src/tests/non262/Tuple/from/iter-adv-err.js create mode 100644 js/src/tests/non262/Tuple/from/iter-get-iter-err.js create mode 100644 js/src/tests/non262/Tuple/from/iter-get-iter-val-err.js create mode 100644 js/src/tests/non262/Tuple/from/iter-map-fn-args.js create mode 100644 js/src/tests/non262/Tuple/from/iter-map-fn-err.js create mode 100644 js/src/tests/non262/Tuple/from/iter-map-fn-return.js create mode 100644 js/src/tests/non262/Tuple/from/iter-map-fn-this-arg.js create mode 100644 js/src/tests/non262/Tuple/from/iter-map-fn-this-non-strict.js create mode 100644 js/src/tests/non262/Tuple/from/iter-map-fn-this-strict-strict.js create mode 100644 js/src/tests/non262/Tuple/from/iter-next-error.js create mode 100644 js/src/tests/non262/Tuple/from/iter-next-value-error.js create mode 100644 js/src/tests/non262/Tuple/from/iter-set-elem-prop.js create mode 100644 js/src/tests/non262/Tuple/from/iter-set-length.js create mode 100644 js/src/tests/non262/Tuple/from/length.js create mode 100644 js/src/tests/non262/Tuple/from/mapfn-is-not-callable-typeerror.js create mode 100644 js/src/tests/non262/Tuple/from/mapfn-throws-exception.js create mode 100644 js/src/tests/non262/Tuple/from/name.js create mode 100644 js/src/tests/non262/Tuple/from/not-a-constructor.js create mode 100644 js/src/tests/non262/Tuple/from/prop-desc.js create mode 100644 js/src/tests/non262/Tuple/from/source-array-boundary.js create mode 100644 js/src/tests/non262/Tuple/from/source-object-iterator-1.js create mode 100644 js/src/tests/non262/Tuple/from/source-object-length.js create mode 100644 js/src/tests/non262/Tuple/from/source-object-without.js create mode 100644 js/src/tests/non262/Tuple/from/this-null.js create mode 100644 js/src/tests/non262/Tuple/gc.js create mode 100644 js/src/tests/non262/Tuple/initializers/6.1.2.1.js create mode 100644 js/src/tests/non262/Tuple/isTuple/8.2.2.1.js create mode 100644 js/src/tests/non262/Tuple/isTuple/descriptor.js create mode 100644 js/src/tests/non262/Tuple/isTuple/length.js create mode 100644 js/src/tests/non262/Tuple/isTuple/name.js create mode 100644 js/src/tests/non262/Tuple/isTuple/not-a-constructor.js create mode 100644 js/src/tests/non262/Tuple/length-ownproperty.js create mode 100644 js/src/tests/non262/Tuple/literal.js create mode 100644 js/src/tests/non262/Tuple/methods.js create mode 100644 js/src/tests/non262/Tuple/of/length.js create mode 100644 js/src/tests/non262/Tuple/of/name.js create mode 100644 js/src/tests/non262/Tuple/of/not-a-constructor.js create mode 100644 js/src/tests/non262/Tuple/of/of.js create mode 100644 js/src/tests/non262/Tuple/of/prop-desc.js create mode 100644 js/src/tests/non262/Tuple/property-descriptors.js create mode 100644 js/src/tests/non262/Tuple/proto-override.js create mode 100644 js/src/tests/non262/Tuple/prototype/Symbol.toStringTag/invoked-as-accessor.js create mode 100644 js/src/tests/non262/Tuple/prototype/Symbol.toStringTag/length.js create mode 100644 js/src/tests/non262/Tuple/prototype/Symbol.toStringTag/name.js create mode 100644 js/src/tests/non262/Tuple/prototype/Symbol.toStringTag/prop-desc.js create mode 100644 js/src/tests/non262/Tuple/prototype/concat/concat-with-array.js create mode 100644 js/src/tests/non262/Tuple/prototype/concat/concat.js create mode 100644 js/src/tests/non262/Tuple/prototype/concat/indexed-setters.js create mode 100644 js/src/tests/non262/Tuple/prototype/concat/length.js create mode 100644 js/src/tests/non262/Tuple/prototype/filter/filter.js create mode 100644 js/src/tests/non262/Tuple/prototype/filter/indexed-setters.js create mode 100644 js/src/tests/non262/Tuple/prototype/filter/length.js create mode 100644 js/src/tests/non262/Tuple/prototype/flat/empty-tuple-elements.js create mode 100644 js/src/tests/non262/Tuple/prototype/flat/flat.js create mode 100644 js/src/tests/non262/Tuple/prototype/flat/indexed-setters.js create mode 100644 js/src/tests/non262/Tuple/prototype/flat/length.js create mode 100644 js/src/tests/non262/Tuple/prototype/flat/undefined-elements.js create mode 100644 js/src/tests/non262/Tuple/prototype/flatMap/depth-always-one.js create mode 100644 js/src/tests/non262/Tuple/prototype/flatMap/flatMap.js create mode 100644 js/src/tests/non262/Tuple/prototype/flatMap/length.js create mode 100644 js/src/tests/non262/Tuple/prototype/includes/fromIndex-equal-or-greater-length-returns-false.js create mode 100644 js/src/tests/non262/Tuple/prototype/includes/fromIndex-infinity.js create mode 100644 js/src/tests/non262/Tuple/prototype/includes/fromIndex-minus-zero.js create mode 100644 js/src/tests/non262/Tuple/prototype/includes/includes.js create mode 100644 js/src/tests/non262/Tuple/prototype/includes/length-internal.js create mode 100644 js/src/tests/non262/Tuple/prototype/includes/length-zero-returns-false.js create mode 100644 js/src/tests/non262/Tuple/prototype/includes/length.js create mode 100644 js/src/tests/non262/Tuple/prototype/includes/name.js create mode 100644 js/src/tests/non262/Tuple/prototype/includes/no-arg.js create mode 100644 js/src/tests/non262/Tuple/prototype/includes/not-a-constructor.js create mode 100644 js/src/tests/non262/Tuple/prototype/includes/prop-desc.js create mode 100644 js/src/tests/non262/Tuple/prototype/includes/return-abrupt-get-length.js create mode 100644 js/src/tests/non262/Tuple/prototype/includes/return-abrupt-tointeger-fromindex-symbol.js create mode 100644 js/src/tests/non262/Tuple/prototype/includes/return-abrupt-tointeger-fromindex.js create mode 100644 js/src/tests/non262/Tuple/prototype/includes/return-abrupt-tonumber-length-symbol.js create mode 100644 js/src/tests/non262/Tuple/prototype/includes/samevaluezero.js create mode 100644 js/src/tests/non262/Tuple/prototype/includes/search-found-returns-true.js create mode 100644 js/src/tests/non262/Tuple/prototype/includes/search-not-found-returns-false.js create mode 100644 js/src/tests/non262/Tuple/prototype/includes/this-is-not-tuple.js create mode 100644 js/src/tests/non262/Tuple/prototype/includes/tointeger-fromindex.js create mode 100644 js/src/tests/non262/Tuple/prototype/includes/using-fromindex.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/empty-tuple.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-boolean.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-float.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-greater-than-length.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-infinity-string.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-inherited-valueOf.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-missing.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-nan.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-neg-infinity.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-neg-zero.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-negative.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-null.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-number.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-object-not-primitive.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-object-valueOf-toString.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-object-valueOf.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-object.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-positive.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-side-effects-3.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-2.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-exponent.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-hex.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-leading-zeros.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-neg-infinity.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string-negative.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-string.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-trunc-2.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-trunc.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-undefined.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-with-index.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/fromIndex-zero.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/includes.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/length-internal.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/length.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/undefined-throws-type-error.js create mode 100644 js/src/tests/non262/Tuple/prototype/indexOf/uses-internal-length.js create mode 100644 js/src/tests/non262/Tuple/prototype/isTuple/isTuple.js create mode 100644 js/src/tests/non262/Tuple/prototype/isTuple/length.js create mode 100644 js/src/tests/non262/Tuple/prototype/join/browser.js create mode 100644 js/src/tests/non262/Tuple/prototype/join/dda-separator.js create mode 100644 js/src/tests/non262/Tuple/prototype/join/shell.js create mode 100644 js/src/tests/non262/Tuple/prototype/length/length-getter.js create mode 100644 js/src/tests/non262/Tuple/prototype/map/callback-not-called-on-empty.js create mode 100644 js/src/tests/non262/Tuple/prototype/map/callbackfn-arguments-with-thisarg create mode 100644 js/src/tests/non262/Tuple/prototype/map/callbackfn-arguments-with-thisarg.js create mode 100644 js/src/tests/non262/Tuple/prototype/map/callbackfn-arguments-without-thisarg.js create mode 100644 js/src/tests/non262/Tuple/prototype/map/callbackfn-is-not-callable.js create mode 100644 js/src/tests/non262/Tuple/prototype/map/callbackfn-returns-abrupt.js create mode 100644 js/src/tests/non262/Tuple/prototype/map/indexed-setters.js create mode 100644 js/src/tests/non262/Tuple/prototype/map/invoked-as-func.js create mode 100644 js/src/tests/non262/Tuple/prototype/map/invoked-as-method.js create mode 100644 js/src/tests/non262/Tuple/prototype/map/length-internal.js create mode 100644 js/src/tests/non262/Tuple/prototype/map/length.js create mode 100644 js/src/tests/non262/Tuple/prototype/map/map.js create mode 100644 js/src/tests/non262/Tuple/prototype/map/this-is-not-tuple.js create mode 100644 js/src/tests/non262/Tuple/prototype/slice/invoked-as-func.js create mode 100644 js/src/tests/non262/Tuple/prototype/slice/invoked-as-method.js create mode 100644 js/src/tests/non262/Tuple/prototype/slice/length.js create mode 100644 js/src/tests/non262/Tuple/prototype/slice/name.js create mode 100644 js/src/tests/non262/Tuple/prototype/slice/negative-zero.js create mode 100644 js/src/tests/non262/Tuple/prototype/slice/not-a-constructor.js create mode 100644 js/src/tests/non262/Tuple/prototype/slice/prop-desc.js create mode 100644 js/src/tests/non262/Tuple/prototype/slice/return-abrupt-from-end.js create mode 100644 js/src/tests/non262/Tuple/prototype/slice/return-abrupt-from-start.js create mode 100644 js/src/tests/non262/Tuple/prototype/slice/slice.js create mode 100644 js/src/tests/non262/Tuple/prototype/slice/tointeger-end.js create mode 100644 js/src/tests/non262/Tuple/prototype/slice/tointeger-start.js create mode 100644 js/src/tests/non262/Tuple/prototype/slice/tuple-length-internal.js create mode 100644 js/src/tests/non262/Tuple/prototype/toReversed/indexed-setters.js create mode 100644 js/src/tests/non262/Tuple/prototype/toReversed/invoked-as-func.js create mode 100644 js/src/tests/non262/Tuple/prototype/toReversed/invoked-as-method.js create mode 100644 js/src/tests/non262/Tuple/prototype/toReversed/length.js create mode 100644 js/src/tests/non262/Tuple/prototype/toReversed/this-is-not-tuple.js create mode 100644 js/src/tests/non262/Tuple/prototype/toReversed/toReversed.js create mode 100644 js/src/tests/non262/Tuple/prototype/toSorted/comparefn-call-throws.js create mode 100644 js/src/tests/non262/Tuple/prototype/toSorted/comparefn-calls.js create mode 100644 js/src/tests/non262/Tuple/prototype/toSorted/comparefn-nonfunction-call-throws.js create mode 100644 js/src/tests/non262/Tuple/prototype/toSorted/invoked-as-func.js create mode 100644 js/src/tests/non262/Tuple/prototype/toSorted/invoked-as-method.js create mode 100644 js/src/tests/non262/Tuple/prototype/toSorted/length.js create mode 100644 js/src/tests/non262/Tuple/prototype/toSorted/sorted-values.js create mode 100644 js/src/tests/non262/Tuple/prototype/toSorted/stability.js create mode 100644 js/src/tests/non262/Tuple/prototype/toSorted/this-is-not-tuple.js create mode 100644 js/src/tests/non262/Tuple/prototype/toSorted/toSorted.js create mode 100644 js/src/tests/non262/Tuple/prototype/toSorted/toSortedcompare-with-no-tostring.js create mode 100644 js/src/tests/non262/Tuple/prototype/toSorted/tuplelength-internal.js create mode 100644 js/src/tests/non262/Tuple/prototype/toSpliced/indexed-setters.js create mode 100644 js/src/tests/non262/Tuple/prototype/toSpliced/length.js create mode 100644 js/src/tests/non262/Tuple/prototype/toSpliced/toSpliced.js create mode 100644 js/src/tests/non262/Tuple/prototype/toString/length.js create mode 100644 js/src/tests/non262/Tuple/prototype/toString/to-string.js create mode 100644 js/src/tests/non262/Tuple/prototype/valueOf/length.js create mode 100644 js/src/tests/non262/Tuple/prototype/valueOf/name.js create mode 100644 js/src/tests/non262/Tuple/prototype/valueOf/valueOf.js create mode 100644 js/src/tests/non262/Tuple/prototype/with/with.js create mode 100644 js/src/tests/non262/Tuple/shell.js create mode 100644 js/src/tests/non262/Tuple/syntax.js create mode 100644 js/src/tests/non262/Tuple/type-errors.js create mode 100644 js/src/tests/non262/Tuple/wrapper.js create mode 100644 js/src/tests/non262/TypedArray/Tconstructor-fromTypedArray-byteLength.js create mode 100644 js/src/tests/non262/TypedArray/at.js create mode 100644 js/src/tests/non262/TypedArray/browser.js create mode 100644 js/src/tests/non262/TypedArray/bug1526838.js create mode 100644 js/src/tests/non262/TypedArray/constructor-ArrayBuffer-species-wrap.js create mode 100644 js/src/tests/non262/TypedArray/constructor-ArrayBuffer-species.js create mode 100644 js/src/tests/non262/TypedArray/constructor-buffer-sequence.js create mode 100644 js/src/tests/non262/TypedArray/constructor-byteoffsets-bounds.js create mode 100644 js/src/tests/non262/TypedArray/constructor-iterable-generator.js create mode 100644 js/src/tests/non262/TypedArray/constructor-iterable-modified-array-iterator-next.js create mode 100644 js/src/tests/non262/TypedArray/constructor-iterable-modified-array-iterator.js create mode 100644 js/src/tests/non262/TypedArray/constructor-iterable-nonpacked-array.js create mode 100644 js/src/tests/non262/TypedArray/constructor-iterable-not-callable.js create mode 100644 js/src/tests/non262/TypedArray/constructor-iterable-packed-array-side-effect.js create mode 100644 js/src/tests/non262/TypedArray/constructor-iterable-packed-array.js create mode 100644 js/src/tests/non262/TypedArray/constructor-iterable-undefined-or-null.js create mode 100644 js/src/tests/non262/TypedArray/constructor-iterator-primitive.js create mode 100644 js/src/tests/non262/TypedArray/constructor-length-too-large.js create mode 100644 js/src/tests/non262/TypedArray/constructor-non-detached.js create mode 100644 js/src/tests/non262/TypedArray/constructor-not-callable.js create mode 100644 js/src/tests/non262/TypedArray/constructor-typedarray-species-other-global.js create mode 100644 js/src/tests/non262/TypedArray/constructor-undefined-args.js create mode 100644 js/src/tests/non262/TypedArray/constructor_bad-args.js create mode 100644 js/src/tests/non262/TypedArray/detached-array-buffer-checks.js create mode 100644 js/src/tests/non262/TypedArray/element-setting-converts-using-ToNumber.js create mode 100644 js/src/tests/non262/TypedArray/entries.js create mode 100644 js/src/tests/non262/TypedArray/every-and-some.js create mode 100644 js/src/tests/non262/TypedArray/fill-detached.js create mode 100644 js/src/tests/non262/TypedArray/fill.js create mode 100644 js/src/tests/non262/TypedArray/filter-species.js create mode 100644 js/src/tests/non262/TypedArray/filter-validation.js create mode 100644 js/src/tests/non262/TypedArray/find-and-findIndex.js create mode 100644 js/src/tests/non262/TypedArray/findLast-and-findLastIndex.js create mode 100644 js/src/tests/non262/TypedArray/forEach.js create mode 100644 js/src/tests/non262/TypedArray/from-iterable-validation.js create mode 100644 js/src/tests/non262/TypedArray/from-non-iterable-validation.js create mode 100644 js/src/tests/non262/TypedArray/from_basics.js create mode 100644 js/src/tests/non262/TypedArray/from_constructor.js create mode 100644 js/src/tests/non262/TypedArray/from_errors.js create mode 100644 js/src/tests/non262/TypedArray/from_iterable.js create mode 100644 js/src/tests/non262/TypedArray/from_mapping.js create mode 100644 js/src/tests/non262/TypedArray/from_realms.js create mode 100644 js/src/tests/non262/TypedArray/from_string.js create mode 100644 js/src/tests/non262/TypedArray/from_surfaces.js create mode 100644 js/src/tests/non262/TypedArray/from_this.js create mode 100644 js/src/tests/non262/TypedArray/from_typedarray_fastpath_detached.js create mode 100644 js/src/tests/non262/TypedArray/getter-name.js create mode 100644 js/src/tests/non262/TypedArray/has-property-op.js create mode 100644 js/src/tests/non262/TypedArray/includes.js create mode 100644 js/src/tests/non262/TypedArray/indexOf-and-lastIndexOf.js create mode 100644 js/src/tests/non262/TypedArray/indexOf-never-returns-negative-zero.js create mode 100644 js/src/tests/non262/TypedArray/iterator-next-with-detached.js create mode 100644 js/src/tests/non262/TypedArray/iterator.js create mode 100644 js/src/tests/non262/TypedArray/join.js create mode 100644 js/src/tests/non262/TypedArray/keys.js create mode 100644 js/src/tests/non262/TypedArray/large-arrays.js create mode 100644 js/src/tests/non262/TypedArray/lastIndexOf-never-returns-negative-zero.js create mode 100644 js/src/tests/non262/TypedArray/length.js create mode 100644 js/src/tests/non262/TypedArray/map-and-filter.js create mode 100644 js/src/tests/non262/TypedArray/map-species.js create mode 100644 js/src/tests/non262/TypedArray/map-validation.js create mode 100644 js/src/tests/non262/TypedArray/object-defineproperty.js create mode 100644 js/src/tests/non262/TypedArray/of-validation.js create mode 100644 js/src/tests/non262/TypedArray/of.js create mode 100644 js/src/tests/non262/TypedArray/prototype-constructor-identity.js create mode 100644 js/src/tests/non262/TypedArray/reduce-and-reduceRight.js create mode 100644 js/src/tests/non262/TypedArray/reverse.js create mode 100644 js/src/tests/non262/TypedArray/seal-and-freeze.js create mode 100644 js/src/tests/non262/TypedArray/set-detached-bigint.js create mode 100644 js/src/tests/non262/TypedArray/set-detached.js create mode 100644 js/src/tests/non262/TypedArray/set-negative-offset.js create mode 100644 js/src/tests/non262/TypedArray/set-same-buffer-different-source-target-types.js create mode 100644 js/src/tests/non262/TypedArray/set-tointeger.js create mode 100644 js/src/tests/non262/TypedArray/set-toobject.js create mode 100644 js/src/tests/non262/TypedArray/set-with-receiver.js create mode 100644 js/src/tests/non262/TypedArray/set-wrapped.js create mode 100644 js/src/tests/non262/TypedArray/set.js create mode 100644 js/src/tests/non262/TypedArray/shell.js create mode 100644 js/src/tests/non262/TypedArray/slice-bitwise.js create mode 100644 js/src/tests/non262/TypedArray/slice-conversion.js create mode 100644 js/src/tests/non262/TypedArray/slice-detached.js create mode 100644 js/src/tests/non262/TypedArray/slice-memcpy.js create mode 100644 js/src/tests/non262/TypedArray/slice-species.js create mode 100644 js/src/tests/non262/TypedArray/slice-validation.js create mode 100644 js/src/tests/non262/TypedArray/slice.js create mode 100644 js/src/tests/non262/TypedArray/sort-negative-nan.js create mode 100644 js/src/tests/non262/TypedArray/sort-non-function.js create mode 100644 js/src/tests/non262/TypedArray/sort_basics.js create mode 100644 js/src/tests/non262/TypedArray/sort_byteoffset.js create mode 100644 js/src/tests/non262/TypedArray/sort_comparators.js create mode 100644 js/src/tests/non262/TypedArray/sort_compare_nan.js create mode 100644 js/src/tests/non262/TypedArray/sort_errors.js create mode 100644 js/src/tests/non262/TypedArray/sort_globals.js create mode 100644 js/src/tests/non262/TypedArray/sort_modifications.js create mode 100644 js/src/tests/non262/TypedArray/sort_modifications_concurrent.js create mode 100644 js/src/tests/non262/TypedArray/sort_modifications_concurrent_radixsort.js create mode 100644 js/src/tests/non262/TypedArray/sort_small.js create mode 100644 js/src/tests/non262/TypedArray/sort_snans.js create mode 100644 js/src/tests/non262/TypedArray/sort_sorted.js create mode 100644 js/src/tests/non262/TypedArray/sort_stable.js create mode 100644 js/src/tests/non262/TypedArray/sorting_buffer_access.js create mode 100644 js/src/tests/non262/TypedArray/subarray-species.js create mode 100644 js/src/tests/non262/TypedArray/subarray-validation.js create mode 100644 js/src/tests/non262/TypedArray/subarray.js create mode 100644 js/src/tests/non262/TypedArray/test-integrity-level-detached.js create mode 100644 js/src/tests/non262/TypedArray/test-integrity-level.js create mode 100644 js/src/tests/non262/TypedArray/toLocaleString-detached.js create mode 100644 js/src/tests/non262/TypedArray/toLocaleString-nointl.js create mode 100644 js/src/tests/non262/TypedArray/toLocaleString.js create mode 100644 js/src/tests/non262/TypedArray/toReversed-detached.js create mode 100644 js/src/tests/non262/TypedArray/toSorted-detached.js create mode 100644 js/src/tests/non262/TypedArray/toString.js create mode 100644 js/src/tests/non262/TypedArray/toStringTag-cross-compartment.js create mode 100644 js/src/tests/non262/TypedArray/uint8clamped-constructor.js create mode 100644 js/src/tests/non262/TypedArray/values.js create mode 100644 js/src/tests/non262/TypedArray/with-detached.js create mode 100644 js/src/tests/non262/TypedArray/with.js create mode 100644 js/src/tests/non262/TypedArray/write-out-of-bounds-tonumber.js create mode 100644 js/src/tests/non262/Unicode/browser.js create mode 100644 js/src/tests/non262/Unicode/non-bmp-non-spaces.js create mode 100644 js/src/tests/non262/Unicode/regress-352044-01.js create mode 100644 js/src/tests/non262/Unicode/regress-352044-02-n.js create mode 100644 js/src/tests/non262/Unicode/shell.js create mode 100644 js/src/tests/non262/Unicode/uc-001-n.js create mode 100644 js/src/tests/non262/Unicode/uc-002-n.js create mode 100644 js/src/tests/non262/Unicode/uc-002.js create mode 100644 js/src/tests/non262/Unicode/uc-003.js create mode 100644 js/src/tests/non262/Unicode/uc-004.js create mode 100644 js/src/tests/non262/Unicode/uc-005.js create mode 100644 js/src/tests/non262/WeakMap/browser.js create mode 100644 js/src/tests/non262/WeakMap/shell.js create mode 100644 js/src/tests/non262/WeakMap/symbols.js create mode 100644 js/src/tests/non262/WeakMap/symbols_not_as_weakmap_keys.js create mode 100644 js/src/tests/non262/arrow-functions/arrow-not-as-end-of-statement.js create mode 100644 js/src/tests/non262/arrow-functions/arrow-returning-arrow-with-block-body-followed-by-regexp.js create mode 100644 js/src/tests/non262/arrow-functions/browser.js create mode 100644 js/src/tests/non262/arrow-functions/shell.js create mode 100644 js/src/tests/non262/arrow-functions/toString-eof.js create mode 100644 js/src/tests/non262/arrow-functions/yield-in-arrow.js create mode 100644 js/src/tests/non262/async-functions/BoundNames.js create mode 100644 js/src/tests/non262/async-functions/EarlyErrors.js create mode 100644 js/src/tests/non262/async-functions/ErrorStack.js create mode 100644 js/src/tests/non262/async-functions/arguments_callee.js create mode 100644 js/src/tests/non262/async-functions/async-contains-unicode-escape.js create mode 100644 js/src/tests/non262/async-functions/async-function-declaration-in-modules.js create mode 100644 js/src/tests/non262/async-functions/async-property-name-error.js create mode 100644 js/src/tests/non262/async-functions/await-error.js create mode 100644 js/src/tests/non262/async-functions/await-in-arrow-parameters.js create mode 100644 js/src/tests/non262/async-functions/await-in-parameters-of-async-func.js create mode 100644 js/src/tests/non262/async-functions/await-newline.js create mode 100644 js/src/tests/non262/async-functions/browser.js create mode 100644 js/src/tests/non262/async-functions/construct-newtarget.js create mode 100644 js/src/tests/non262/async-functions/constructor.js create mode 100644 js/src/tests/non262/async-functions/cover-init-name-syntax.js create mode 100644 js/src/tests/non262/async-functions/create-function-parse-before-getprototype.js create mode 100644 js/src/tests/non262/async-functions/duplicate-__proto__.js create mode 100644 js/src/tests/non262/async-functions/forbidden-as-consequent.js create mode 100644 js/src/tests/non262/async-functions/identity.js create mode 100644 js/src/tests/non262/async-functions/inner-caller.js create mode 100644 js/src/tests/non262/async-functions/length.js create mode 100644 js/src/tests/non262/async-functions/methods.js create mode 100644 js/src/tests/non262/async-functions/no-expression-closure.js create mode 100644 js/src/tests/non262/async-functions/parameters-error-reject-promise.js create mode 100644 js/src/tests/non262/async-functions/properties.js create mode 100644 js/src/tests/non262/async-functions/property.js create mode 100644 js/src/tests/non262/async-functions/semantics.js create mode 100644 js/src/tests/non262/async-functions/shell.js create mode 100644 js/src/tests/non262/async-functions/subclass.js create mode 100644 js/src/tests/non262/async-functions/syntax-arrow.js create mode 100644 js/src/tests/non262/async-functions/syntax-modules.js create mode 100644 js/src/tests/non262/async-functions/syntax.js create mode 100644 js/src/tests/non262/async-functions/toSource.js create mode 100644 js/src/tests/non262/async-functions/toString.js create mode 100644 js/src/tests/non262/async-functions/yield.js create mode 100644 js/src/tests/non262/browser.js create mode 100644 js/src/tests/non262/class/boundFunctionSubclassing.js create mode 100644 js/src/tests/non262/class/browser.js create mode 100644 js/src/tests/non262/class/bytecodePatternMatching.js create mode 100644 js/src/tests/non262/class/classConstructorNoCall.js create mode 100644 js/src/tests/non262/class/classHeritage.js create mode 100644 js/src/tests/non262/class/className.js create mode 100644 js/src/tests/non262/class/classPrototype.js create mode 100644 js/src/tests/non262/class/compPropDestr.js create mode 100644 js/src/tests/non262/class/compPropNames.js create mode 100644 js/src/tests/non262/class/constructorCalled.js create mode 100644 js/src/tests/non262/class/defaultConstructorBase.js create mode 100644 js/src/tests/non262/class/defaultConstructorDerivedSpread.js create mode 100644 js/src/tests/non262/class/defaultConstructorNotCallable.js create mode 100644 js/src/tests/non262/class/derivedConstructorArrowEvalBinding.js create mode 100644 js/src/tests/non262/class/derivedConstructorArrowEvalClosed.js create mode 100644 js/src/tests/non262/class/derivedConstructorArrowEvalEscape.js create mode 100644 js/src/tests/non262/class/derivedConstructorArrowEvalEscapeUninitialized.js create mode 100644 js/src/tests/non262/class/derivedConstructorArrowEvalGetThis.js create mode 100644 js/src/tests/non262/class/derivedConstructorArrowEvalNestedSuperCall.js create mode 100644 js/src/tests/non262/class/derivedConstructorArrowEvalSuperCall.js create mode 100644 js/src/tests/non262/class/derivedConstructorInlining.js create mode 100644 js/src/tests/non262/class/derivedConstructorName.js create mode 100644 js/src/tests/non262/class/derivedConstructorReturnPrimitive.js create mode 100644 js/src/tests/non262/class/derivedConstructorTDZExplicitThis.js create mode 100644 js/src/tests/non262/class/derivedConstructorTDZOffEdge.js create mode 100644 js/src/tests/non262/class/derivedConstructorTDZReturnAliasedTry.js create mode 100644 js/src/tests/non262/class/derivedConstructorTDZReturnObject.js create mode 100644 js/src/tests/non262/class/derivedConstructorTDZReturnTry.js create mode 100644 js/src/tests/non262/class/derivedConstructorTDZReturnUndefined.js create mode 100644 js/src/tests/non262/class/extendBuiltinConstructors.js create mode 100644 js/src/tests/non262/class/fields-instance-class-name-binding-eval.js create mode 100644 js/src/tests/non262/class/fields-instance-class-name-binding.js create mode 100644 js/src/tests/non262/class/fields-static-class-name-binding-eval.js create mode 100644 js/src/tests/non262/class/fields-static-class-name-binding.js create mode 100644 js/src/tests/non262/class/geterNoExprClosure.js create mode 100644 js/src/tests/non262/class/innerBinding.js create mode 100644 js/src/tests/non262/class/member-expr-after-super.js create mode 100644 js/src/tests/non262/class/methDefn.js create mode 100644 js/src/tests/non262/class/methDefnGen.js create mode 100644 js/src/tests/non262/class/method-named-static.js create mode 100644 js/src/tests/non262/class/methodInstallation.js create mode 100644 js/src/tests/non262/class/methodName.js create mode 100644 js/src/tests/non262/class/methodOverwrites.js create mode 100644 js/src/tests/non262/class/methodsPrototype.js create mode 100644 js/src/tests/non262/class/newTargetArgumentsIntact.js create mode 100644 js/src/tests/non262/class/newTargetArrow.js create mode 100644 js/src/tests/non262/class/newTargetBound.js create mode 100644 js/src/tests/non262/class/newTargetCCW.js create mode 100644 js/src/tests/non262/class/newTargetDVG.js create mode 100644 js/src/tests/non262/class/newTargetDefaults.js create mode 100644 js/src/tests/non262/class/newTargetDirectInvoke.js create mode 100644 js/src/tests/non262/class/newTargetEval.js create mode 100644 js/src/tests/non262/class/newTargetGenerators.js create mode 100644 js/src/tests/non262/class/newTargetMethods.js create mode 100644 js/src/tests/non262/class/newTargetNonFunction.js create mode 100644 js/src/tests/non262/class/newTargetProxyNative.js create mode 100644 js/src/tests/non262/class/outerBinding.js create mode 100644 js/src/tests/non262/class/parenExprToString.js create mode 100644 js/src/tests/non262/class/shell.js create mode 100644 js/src/tests/non262/class/staticConstructor.js create mode 100644 js/src/tests/non262/class/staticMethods.js create mode 100644 js/src/tests/non262/class/strictExecution.js create mode 100644 js/src/tests/non262/class/stringConstructor.js create mode 100644 js/src/tests/non262/class/subclassedArrayUnboxed.js create mode 100644 js/src/tests/non262/class/superCallBadDynamicSuperClass.js create mode 100644 js/src/tests/non262/class/superCallBadNewTargetPrototype.js create mode 100644 js/src/tests/non262/class/superCallBaseInvoked.js create mode 100644 js/src/tests/non262/class/superCallIllegal.js create mode 100644 js/src/tests/non262/class/superCallInvalidBase.js create mode 100644 js/src/tests/non262/class/superCallOrder.js create mode 100644 js/src/tests/non262/class/superCallProperBase.js create mode 100644 js/src/tests/non262/class/superCallSpreadCall.js create mode 100644 js/src/tests/non262/class/superCallThisInit.js create mode 100644 js/src/tests/non262/class/superElemDelete.js create mode 100644 js/src/tests/non262/class/superPropBasicCalls.js create mode 100644 js/src/tests/non262/class/superPropBasicChain.js create mode 100644 js/src/tests/non262/class/superPropBasicGetter.js create mode 100644 js/src/tests/non262/class/superPropBasicNew.js create mode 100644 js/src/tests/non262/class/superPropChains.js create mode 100644 js/src/tests/non262/class/superPropDVG.js create mode 100644 js/src/tests/non262/class/superPropDelete.js create mode 100644 js/src/tests/non262/class/superPropDerivedCalls.js create mode 100644 js/src/tests/non262/class/superPropDestructuring.js create mode 100644 js/src/tests/non262/class/superPropEvalInsideArrow.js create mode 100644 js/src/tests/non262/class/superPropEvalInsideNested.js create mode 100644 js/src/tests/non262/class/superPropFor.js create mode 100644 js/src/tests/non262/class/superPropHeavyweightArrow.js create mode 100644 js/src/tests/non262/class/superPropHomeObject.js create mode 100644 js/src/tests/non262/class/superPropIncDecElem.js create mode 100644 js/src/tests/non262/class/superPropLazyInnerFunction.js create mode 100644 js/src/tests/non262/class/superPropNoOverwriting.js create mode 100644 js/src/tests/non262/class/superPropOrdering.js create mode 100644 js/src/tests/non262/class/superPropProtoChanges.js create mode 100644 js/src/tests/non262/class/superPropProxies.js create mode 100644 js/src/tests/non262/class/superPropSkips.js create mode 100644 js/src/tests/non262/class/superPropStatics.js create mode 100644 js/src/tests/non262/class/superPropStrictAssign.js create mode 100644 js/src/tests/non262/class/superThisStrictNoBoxing.js create mode 100644 js/src/tests/non262/class/uninitializedThisError.js create mode 100644 js/src/tests/non262/comprehensions/browser.js create mode 100644 js/src/tests/non262/comprehensions/shell.js create mode 100644 js/src/tests/non262/destructuring/array-default-class.js create mode 100644 js/src/tests/non262/destructuring/array-iterator-close.js create mode 100644 js/src/tests/non262/destructuring/browser.js create mode 100644 js/src/tests/non262/destructuring/bug1396261.js create mode 100644 js/src/tests/non262/destructuring/constant-folding.js create mode 100644 js/src/tests/non262/destructuring/cover-init-name-syntax.js create mode 100644 js/src/tests/non262/destructuring/duplicate-__proto__.js create mode 100644 js/src/tests/non262/destructuring/iterator-primitive.js create mode 100644 js/src/tests/non262/destructuring/order-super.js create mode 100644 js/src/tests/non262/destructuring/order.js create mode 100644 js/src/tests/non262/destructuring/rest-parameter-aray-iterator.js create mode 100644 js/src/tests/non262/destructuring/rest-parameter-arguments.js create mode 100644 js/src/tests/non262/destructuring/rest-parameter-function-length.js create mode 100644 js/src/tests/non262/destructuring/rest-parameter-spread-call-optimization.js create mode 100644 js/src/tests/non262/destructuring/rest-parameter-syntax.js create mode 100644 js/src/tests/non262/destructuring/rest-parameter.js create mode 100644 js/src/tests/non262/destructuring/rest-with-trailing-comma.js create mode 100644 js/src/tests/non262/destructuring/shell.js create mode 100644 js/src/tests/non262/destructuring/yield-in-object-destr-function.js create mode 100644 js/src/tests/non262/destructuring/yield-in-object-destr-generator.js create mode 100644 js/src/tests/non262/destructuring/yield-in-object-destr-script.js create mode 100644 js/src/tests/non262/destructuring/yield-with-escape-in-object-destr-function.js create mode 100644 js/src/tests/non262/destructuring/yield-with-escape-in-object-destr-generator.js create mode 100644 js/src/tests/non262/destructuring/yield-with-escape-in-object-destr-script.js create mode 100644 js/src/tests/non262/eval/browser.js create mode 100644 js/src/tests/non262/eval/exhaustive-fun-normalcaller-direct-normalcode.js create mode 100644 js/src/tests/non262/eval/exhaustive-fun-normalcaller-direct-strictcode.js create mode 100644 js/src/tests/non262/eval/exhaustive-fun-normalcaller-indirect-normalcode.js create mode 100644 js/src/tests/non262/eval/exhaustive-fun-normalcaller-indirect-strictcode.js create mode 100644 js/src/tests/non262/eval/exhaustive-fun-strictcaller-direct-normalcode.js create mode 100644 js/src/tests/non262/eval/exhaustive-fun-strictcaller-direct-strictcode.js create mode 100644 js/src/tests/non262/eval/exhaustive-fun-strictcaller-indirect-normalcode.js create mode 100644 js/src/tests/non262/eval/exhaustive-fun-strictcaller-indirect-strictcode.js create mode 100644 js/src/tests/non262/eval/exhaustive-global-normalcaller-direct-normalcode.js create mode 100644 js/src/tests/non262/eval/exhaustive-global-normalcaller-direct-strictcode.js create mode 100644 js/src/tests/non262/eval/exhaustive-global-normalcaller-indirect-normalcode.js create mode 100644 js/src/tests/non262/eval/exhaustive-global-normalcaller-indirect-strictcode.js create mode 100644 js/src/tests/non262/eval/exhaustive-global-strictcaller-direct-normalcode.js create mode 100644 js/src/tests/non262/eval/exhaustive-global-strictcaller-direct-strictcode.js create mode 100644 js/src/tests/non262/eval/exhaustive-global-strictcaller-indirect-normalcode.js create mode 100644 js/src/tests/non262/eval/exhaustive-global-strictcaller-indirect-strictcode.js create mode 100644 js/src/tests/non262/eval/line-terminator-paragraph-terminator.js create mode 100644 js/src/tests/non262/eval/redeclared-arguments-in-param-expression-eval.js create mode 100644 js/src/tests/non262/eval/regress-531682.js create mode 100644 js/src/tests/non262/eval/shell.js create mode 100644 js/src/tests/non262/eval/undeclared-name-in-nested-strict-eval.js create mode 100644 js/src/tests/non262/execution-contexts/browser.js create mode 100644 js/src/tests/non262/execution-contexts/regress-23346.js create mode 100644 js/src/tests/non262/execution-contexts/regress-448595-01.js create mode 100644 js/src/tests/non262/execution-contexts/shell.js create mode 100644 js/src/tests/non262/expressions/11.1.5-01.js create mode 100644 js/src/tests/non262/expressions/ToPropertyKey-symbols.js create mode 100644 js/src/tests/non262/expressions/binary-literals.js create mode 100644 js/src/tests/non262/expressions/browser.js create mode 100644 js/src/tests/non262/expressions/computed-property-side-effects.js create mode 100644 js/src/tests/non262/expressions/constant-folded-labeled-statement.js create mode 100644 js/src/tests/non262/expressions/delete-constant-folded-and-or.js create mode 100644 js/src/tests/non262/expressions/delete-name-parenthesized-early-error-strict-mode.js create mode 100644 js/src/tests/non262/expressions/destructuring-array-default-call.js create mode 100644 js/src/tests/non262/expressions/destructuring-array-default-class.js create mode 100644 js/src/tests/non262/expressions/destructuring-array-default-function-nested.js create mode 100644 js/src/tests/non262/expressions/destructuring-array-default-function.js create mode 100644 js/src/tests/non262/expressions/destructuring-array-default-simple.js create mode 100644 js/src/tests/non262/expressions/destructuring-array-default-yield.js create mode 100644 js/src/tests/non262/expressions/destructuring-array-done.js create mode 100644 js/src/tests/non262/expressions/destructuring-array-lexical.js create mode 100644 js/src/tests/non262/expressions/destructuring-object-__proto__-1.js create mode 100644 js/src/tests/non262/expressions/destructuring-object-__proto__-2.js create mode 100644 js/src/tests/non262/expressions/destructuring-pattern-parenthesized.js create mode 100644 js/src/tests/non262/expressions/destructuring-scope.js create mode 100644 js/src/tests/non262/expressions/exponentiation-unparenthesised-unary.js create mode 100644 js/src/tests/non262/expressions/inNotObjectError.js create mode 100644 js/src/tests/non262/expressions/named-accessor-function.js create mode 100644 js/src/tests/non262/expressions/nested-delete-name-in-evalcode.js create mode 100644 js/src/tests/non262/expressions/nullish-coalescing.js create mode 100644 js/src/tests/non262/expressions/object-literal-__proto__.js create mode 100644 js/src/tests/non262/expressions/object-literal-accessor-arguments.js create mode 100644 js/src/tests/non262/expressions/object-literal-accessor-property-name.js create mode 100644 js/src/tests/non262/expressions/object-literal-computed-property-evaluation.js create mode 100644 js/src/tests/non262/expressions/octal-literals.js create mode 100644 js/src/tests/non262/expressions/optional-chain-class-heritage.js create mode 100644 js/src/tests/non262/expressions/optional-chain-first-expression.js create mode 100644 js/src/tests/non262/expressions/optional-chain-super-elem.js create mode 100644 js/src/tests/non262/expressions/optional-chain-tdz.js create mode 100644 js/src/tests/non262/expressions/optional-chain.js create mode 100644 js/src/tests/non262/expressions/primitive-this-boxing-behavior.js create mode 100644 js/src/tests/non262/expressions/regress-192288.js create mode 100644 js/src/tests/non262/expressions/regress-346203.js create mode 100644 js/src/tests/non262/expressions/regress-346645-01.js create mode 100644 js/src/tests/non262/expressions/regress-346645-02.js create mode 100644 js/src/tests/non262/expressions/regress-346645-03.js create mode 100644 js/src/tests/non262/expressions/regress-394673.js create mode 100644 js/src/tests/non262/expressions/regress-418051.js create mode 100644 js/src/tests/non262/expressions/regress-451340.js create mode 100644 js/src/tests/non262/expressions/regress-96526-argsub.js create mode 100644 js/src/tests/non262/expressions/regress-96526-delelem.js create mode 100644 js/src/tests/non262/expressions/regress-96526-noargsub.js create mode 100644 js/src/tests/non262/expressions/shell.js create mode 100644 js/src/tests/non262/expressions/short-circuit-compound-assignment-anon-fns.js create mode 100644 js/src/tests/non262/expressions/short-circuit-compound-assignment-const.js create mode 100644 js/src/tests/non262/expressions/short-circuit-compound-assignment-deleted-decl-binding.js create mode 100644 js/src/tests/non262/expressions/short-circuit-compound-assignment-property-key-evaluation.js create mode 100644 js/src/tests/non262/expressions/short-circuit-compound-assignment-scope-lookup.js create mode 100644 js/src/tests/non262/expressions/short-circuit-compound-assignment-tdz.js create mode 100644 js/src/tests/non262/expressions/short-circuit-compound-assignment.js create mode 100644 js/src/tests/non262/expressions/string-literal-escape-sequences.js create mode 100644 js/src/tests/non262/expressions/tagged-template-constant-folding.js create mode 100644 js/src/tests/non262/expressions/trailing_comma_arguments.js create mode 100644 js/src/tests/non262/expressions/trailing_comma_arrow.js create mode 100644 js/src/tests/non262/expressions/trailing_comma_getter_setter.js create mode 100644 js/src/tests/non262/expressions/trailing_comma_parameters.js create mode 100644 js/src/tests/non262/extensions/15.9.4.2.js create mode 100644 js/src/tests/non262/extensions/8.12.5-01.js create mode 100644 js/src/tests/non262/extensions/ArrayBuffer-slice-arguments-detaching.js create mode 100644 js/src/tests/non262/extensions/Boolean-toSource.js create mode 100644 js/src/tests/non262/extensions/DataView-construct-arguments-detaching.js create mode 100644 js/src/tests/non262/extensions/DataView-set-arguments-detaching.js create mode 100644 js/src/tests/non262/extensions/Number-toSource.js create mode 100644 js/src/tests/non262/extensions/RegExp-error-message-skip-selfhosted-frames.js create mode 100644 js/src/tests/non262/extensions/String-match-flags.js create mode 100644 js/src/tests/non262/extensions/String-methods-infinite-recursion.js create mode 100644 js/src/tests/non262/extensions/String-toSource.js create mode 100644 js/src/tests/non262/extensions/TypedArray-set-object-funky-length-detaches.js create mode 100644 js/src/tests/non262/extensions/TypedArray-subarray-arguments-detaching.js create mode 100644 js/src/tests/non262/extensions/__proto__.js create mode 100644 js/src/tests/non262/extensions/arguments-property-access-in-function.js create mode 100644 js/src/tests/non262/extensions/array-inherited-__proto__.js create mode 100644 js/src/tests/non262/extensions/array-isArray-proxy-recursion.js create mode 100644 js/src/tests/non262/extensions/array-length-protochange.js create mode 100644 js/src/tests/non262/extensions/array-pop-proxy.js create mode 100644 js/src/tests/non262/extensions/array-toString-recursion.js create mode 100644 js/src/tests/non262/extensions/arraybuffer-prototype.js create mode 100644 js/src/tests/non262/extensions/bad-regexp-data-clone.js create mode 100644 js/src/tests/non262/extensions/basic-for-each.js create mode 100644 js/src/tests/non262/extensions/basic-for-in.js create mode 100644 js/src/tests/non262/extensions/browser.js create mode 100644 js/src/tests/non262/extensions/bug472534.js create mode 100644 js/src/tests/non262/extensions/builtin-function-arguments-caller.js create mode 100644 js/src/tests/non262/extensions/censor-strict-caller.js create mode 100644 js/src/tests/non262/extensions/clone-bigint.js create mode 100644 js/src/tests/non262/extensions/clone-complex-object.js create mode 100644 js/src/tests/non262/extensions/clone-errors.js create mode 100644 js/src/tests/non262/extensions/clone-forge.js create mode 100644 js/src/tests/non262/extensions/clone-invalid-property-key.js create mode 100644 js/src/tests/non262/extensions/clone-leaf-object.js create mode 100644 js/src/tests/non262/extensions/clone-many-transferables.js create mode 100644 js/src/tests/non262/extensions/clone-object-deep.js create mode 100644 js/src/tests/non262/extensions/clone-object.js create mode 100644 js/src/tests/non262/extensions/clone-regexp.js create mode 100644 js/src/tests/non262/extensions/clone-sab-failure.js create mode 100644 js/src/tests/non262/extensions/clone-sab.js create mode 100644 js/src/tests/non262/extensions/clone-simple.js create mode 100644 js/src/tests/non262/extensions/clone-transferables.js create mode 100644 js/src/tests/non262/extensions/clone-typed-array.js create mode 100644 js/src/tests/non262/extensions/clone-v1-typed-array-data.dat create mode 100644 js/src/tests/non262/extensions/clone-v1-typed-array.js create mode 100644 js/src/tests/non262/extensions/collect-gray.js create mode 100644 js/src/tests/non262/extensions/column-numbers.js create mode 100644 js/src/tests/non262/extensions/cross-global-eval-is-indirect.js create mode 100644 js/src/tests/non262/extensions/cross-global-getPrototypeOf.js create mode 100644 js/src/tests/non262/extensions/dataview.js create mode 100644 js/src/tests/non262/extensions/decompile-for-of.js create mode 100644 js/src/tests/non262/extensions/destructure-accessor.js create mode 100644 js/src/tests/non262/extensions/destructuring-__proto__-shorthand-assignment-before-var.js create mode 100644 js/src/tests/non262/extensions/destructuring-__proto__-shorthand-assignment.js create mode 100644 js/src/tests/non262/extensions/destructuring-__proto__-target-assignment.js create mode 100644 js/src/tests/non262/extensions/destructuring-for-inof-__proto__.js create mode 100644 js/src/tests/non262/extensions/destructuring-order.js create mode 100644 js/src/tests/non262/extensions/element-setting-ToNumber-detaches.js create mode 100644 js/src/tests/non262/extensions/empty.txt create mode 100644 js/src/tests/non262/extensions/error-tostring-function.js create mode 100644 js/src/tests/non262/extensions/errorcolumnblame.js create mode 100644 js/src/tests/non262/extensions/es5ish-defineGetter-defineSetter.js create mode 100644 js/src/tests/non262/extensions/eval-native-callback-is-indirect.js create mode 100644 js/src/tests/non262/extensions/expression-closure-syntax.js create mode 100644 js/src/tests/non262/extensions/extension-methods-reject-null-undefined-this.js create mode 100644 js/src/tests/non262/extensions/file-mapped-arraybuffers.js create mode 100644 js/src/tests/non262/extensions/file-mapped-arraybuffers.txt create mode 100644 js/src/tests/non262/extensions/for-loop-with-lexical-declaration-and-nested-function-statement.js create mode 100644 js/src/tests/non262/extensions/function-caller-skips-eval-frames.js create mode 100644 js/src/tests/non262/extensions/function-caller-strict-cross-global.js create mode 100644 js/src/tests/non262/extensions/function-definition-with.js create mode 100644 js/src/tests/non262/extensions/function-properties.js create mode 100644 js/src/tests/non262/extensions/getOwnPropertyNames-__proto__.js create mode 100644 js/src/tests/non262/extensions/getset-001.js create mode 100644 js/src/tests/non262/extensions/getset-003.js create mode 100644 js/src/tests/non262/extensions/getset-004.js create mode 100644 js/src/tests/non262/extensions/getset-005.js create mode 100644 js/src/tests/non262/extensions/getset-006.js create mode 100644 js/src/tests/non262/extensions/inc-dec-functioncall.js create mode 100644 js/src/tests/non262/extensions/keyword-unescaped-requirement-modules.js create mode 100644 js/src/tests/non262/extensions/keyword-unescaped-requirement.js create mode 100644 js/src/tests/non262/extensions/mutable-proto-special-form.js create mode 100644 js/src/tests/non262/extensions/nested-delete-name-in-evalcode.js create mode 100644 js/src/tests/non262/extensions/new-cross-compartment.js create mode 100644 js/src/tests/non262/extensions/new-parenthesization.js create mode 100644 js/src/tests/non262/extensions/newer-type-functions-caller-arguments.js create mode 100644 js/src/tests/non262/extensions/non_syntactic.js create mode 100644 js/src/tests/non262/extensions/object-toSource-override-on-getter.js create mode 100644 js/src/tests/non262/extensions/object-toSource-undefined-getter.js create mode 100644 js/src/tests/non262/extensions/object-toSource-with-symbol-keys.js create mode 100644 js/src/tests/non262/extensions/parse-rest-destructuring-parameter.js create mode 100644 js/src/tests/non262/extensions/preventExtensions-cross-global.js create mode 100644 js/src/tests/non262/extensions/proxy-array-target-length-definition.js create mode 100644 js/src/tests/non262/extensions/proxy-enumeration.js create mode 100644 js/src/tests/non262/extensions/proxy-proto-setter.js create mode 100644 js/src/tests/non262/extensions/proxy-strict.js create mode 100644 js/src/tests/non262/extensions/quote-string-for-nul-character.js create mode 100644 js/src/tests/non262/extensions/recursion.js create mode 100644 js/src/tests/non262/extensions/redeclaration-of-catch-warning.js create mode 100644 js/src/tests/non262/extensions/reentrant-RegExp-creation-and-gc-during-new-RegExp-pattern-ToString.js create mode 100644 js/src/tests/non262/extensions/regress-103087.js create mode 100644 js/src/tests/non262/extensions/regress-104077.js create mode 100644 js/src/tests/non262/extensions/regress-178722.js create mode 100644 js/src/tests/non262/extensions/regress-188206-01.js create mode 100644 js/src/tests/non262/extensions/regress-188206-02.js create mode 100644 js/src/tests/non262/extensions/regress-192465.js create mode 100644 js/src/tests/non262/extensions/regress-220367-002.js create mode 100644 js/src/tests/non262/extensions/regress-226078.js create mode 100644 js/src/tests/non262/extensions/regress-228087.js create mode 100644 js/src/tests/non262/extensions/regress-245148.js create mode 100644 js/src/tests/non262/extensions/regress-255245.js create mode 100644 js/src/tests/non262/extensions/regress-274152.js create mode 100644 js/src/tests/non262/extensions/regress-300079.js create mode 100644 js/src/tests/non262/extensions/regress-311161.js create mode 100644 js/src/tests/non262/extensions/regress-311792-01.js create mode 100644 js/src/tests/non262/extensions/regress-311792-02.js create mode 100644 js/src/tests/non262/extensions/regress-313763.js create mode 100644 js/src/tests/non262/extensions/regress-314874.js create mode 100644 js/src/tests/non262/extensions/regress-315509-02.js create mode 100644 js/src/tests/non262/extensions/regress-319683.js create mode 100644 js/src/tests/non262/extensions/regress-320854.js create mode 100644 js/src/tests/non262/extensions/regress-327170.js create mode 100644 js/src/tests/non262/extensions/regress-327608.js create mode 100644 js/src/tests/non262/extensions/regress-328443.js create mode 100644 js/src/tests/non262/extensions/regress-333541.js create mode 100644 js/src/tests/non262/extensions/regress-336409-1.js create mode 100644 js/src/tests/non262/extensions/regress-336409-2.js create mode 100644 js/src/tests/non262/extensions/regress-336410-1.js create mode 100644 js/src/tests/non262/extensions/regress-336410-2.js create mode 100644 js/src/tests/non262/extensions/regress-339685.js create mode 100644 js/src/tests/non262/extensions/regress-341956-01.js create mode 100644 js/src/tests/non262/extensions/regress-341956-02.js create mode 100644 js/src/tests/non262/extensions/regress-341956-03.js create mode 100644 js/src/tests/non262/extensions/regress-342960.js create mode 100644 js/src/tests/non262/extensions/regress-346642-06.js create mode 100644 js/src/tests/non262/extensions/regress-346773.js create mode 100644 js/src/tests/non262/extensions/regress-350312-01.js create mode 100644 js/src/tests/non262/extensions/regress-350312.js create mode 100644 js/src/tests/non262/extensions/regress-351070-02.js create mode 100644 js/src/tests/non262/extensions/regress-351463-01.js create mode 100644 js/src/tests/non262/extensions/regress-351973.js create mode 100644 js/src/tests/non262/extensions/regress-352291.js create mode 100644 js/src/tests/non262/extensions/regress-352372.js create mode 100644 js/src/tests/non262/extensions/regress-352604.js create mode 100644 js/src/tests/non262/extensions/regress-353116.js create mode 100644 js/src/tests/non262/extensions/regress-353214-02.js create mode 100644 js/src/tests/non262/extensions/regress-354297.js create mode 100644 js/src/tests/non262/extensions/regress-355052-01.js create mode 100644 js/src/tests/non262/extensions/regress-355052-02.js create mode 100644 js/src/tests/non262/extensions/regress-355052-03.js create mode 100644 js/src/tests/non262/extensions/regress-355410.js create mode 100644 js/src/tests/non262/extensions/regress-355497.js create mode 100644 js/src/tests/non262/extensions/regress-363040-01.js create mode 100644 js/src/tests/non262/extensions/regress-363040-02.js create mode 100644 js/src/tests/non262/extensions/regress-363258.js create mode 100644 js/src/tests/non262/extensions/regress-363988.js create mode 100644 js/src/tests/non262/extensions/regress-365527.js create mode 100644 js/src/tests/non262/extensions/regress-365692.js create mode 100644 js/src/tests/non262/extensions/regress-365869.js create mode 100644 js/src/tests/non262/extensions/regress-366288.js create mode 100644 js/src/tests/non262/extensions/regress-366292.js create mode 100644 js/src/tests/non262/extensions/regress-366396.js create mode 100644 js/src/tests/non262/extensions/regress-366668-01.js create mode 100644 js/src/tests/non262/extensions/regress-367501-01.js create mode 100644 js/src/tests/non262/extensions/regress-367501-02.js create mode 100644 js/src/tests/non262/extensions/regress-367501-03.js create mode 100644 js/src/tests/non262/extensions/regress-367501-04.js create mode 100644 js/src/tests/non262/extensions/regress-367589.js create mode 100644 js/src/tests/non262/extensions/regress-368213.js create mode 100644 js/src/tests/non262/extensions/regress-368224.js create mode 100644 js/src/tests/non262/extensions/regress-368516.js create mode 100644 js/src/tests/non262/extensions/regress-369404.js create mode 100644 js/src/tests/non262/extensions/regress-369696-01.js create mode 100644 js/src/tests/non262/extensions/regress-369696-02.js create mode 100644 js/src/tests/non262/extensions/regress-369696-03.js create mode 100644 js/src/tests/non262/extensions/regress-372309.js create mode 100644 js/src/tests/non262/extensions/regress-375183.js create mode 100644 js/src/tests/non262/extensions/regress-375344.js create mode 100644 js/src/tests/non262/extensions/regress-379566.js create mode 100644 js/src/tests/non262/extensions/regress-380889.js create mode 100644 js/src/tests/non262/extensions/regress-381303.js create mode 100644 js/src/tests/non262/extensions/regress-381304.js create mode 100644 js/src/tests/non262/extensions/regress-385393-02.js create mode 100644 js/src/tests/non262/extensions/regress-385393-08.js create mode 100644 js/src/tests/non262/extensions/regress-390598.js create mode 100644 js/src/tests/non262/extensions/regress-394967.js create mode 100644 js/src/tests/non262/extensions/regress-396326-01.js create mode 100644 js/src/tests/non262/extensions/regress-396326.js create mode 100644 js/src/tests/non262/extensions/regress-406572.js create mode 100644 js/src/tests/non262/extensions/regress-407501.js create mode 100644 js/src/tests/non262/extensions/regress-407720.js create mode 100644 js/src/tests/non262/extensions/regress-412926.js create mode 100644 js/src/tests/non262/extensions/regress-414098.js create mode 100644 js/src/tests/non262/extensions/regress-414755.js create mode 100644 js/src/tests/non262/extensions/regress-416354.js create mode 100644 js/src/tests/non262/extensions/regress-416460.js create mode 100644 js/src/tests/non262/extensions/regress-416834.js create mode 100644 js/src/tests/non262/extensions/regress-420869-01.js create mode 100644 js/src/tests/non262/extensions/regress-422592.js create mode 100644 js/src/tests/non262/extensions/regress-424683-01.js create mode 100644 js/src/tests/non262/extensions/regress-426711.js create mode 100644 js/src/tests/non262/extensions/regress-427196-01.js create mode 100644 js/src/tests/non262/extensions/regress-427196-02.js create mode 100644 js/src/tests/non262/extensions/regress-427196-03.js create mode 100644 js/src/tests/non262/extensions/regress-429739.js create mode 100644 js/src/tests/non262/extensions/regress-430740.js create mode 100644 js/src/tests/non262/extensions/regress-434837-01.js create mode 100644 js/src/tests/non262/extensions/regress-435497-01.js create mode 100644 js/src/tests/non262/extensions/regress-435497-02.js create mode 100644 js/src/tests/non262/extensions/regress-435497-03.js create mode 100644 js/src/tests/non262/extensions/regress-436741.js create mode 100644 js/src/tests/non262/extensions/regress-437288-01.js create mode 100644 js/src/tests/non262/extensions/regress-44009.js create mode 100644 js/src/tests/non262/extensions/regress-443569.js create mode 100644 js/src/tests/non262/extensions/regress-446386.js create mode 100644 js/src/tests/non262/extensions/regress-452168.js create mode 100644 js/src/tests/non262/extensions/regress-452178.js create mode 100644 js/src/tests/non262/extensions/regress-452329.js create mode 100644 js/src/tests/non262/extensions/regress-452338.js create mode 100644 js/src/tests/non262/extensions/regress-452498-162.js create mode 100644 js/src/tests/non262/extensions/regress-452498-196.js create mode 100644 js/src/tests/non262/extensions/regress-452565.js create mode 100644 js/src/tests/non262/extensions/regress-452913.js create mode 100644 js/src/tests/non262/extensions/regress-453249.js create mode 100644 js/src/tests/non262/extensions/regress-454744.js create mode 100644 js/src/tests/non262/extensions/regress-455380.js create mode 100644 js/src/tests/non262/extensions/regress-455408.js create mode 100644 js/src/tests/non262/extensions/regress-456826.js create mode 100644 js/src/tests/non262/extensions/regress-459606.js create mode 100644 js/src/tests/non262/extensions/regress-462734-02.js create mode 100644 js/src/tests/non262/extensions/regress-462734-03.js create mode 100644 js/src/tests/non262/extensions/regress-462734-04.js create mode 100644 js/src/tests/non262/extensions/regress-465276.js create mode 100644 js/src/tests/non262/extensions/regress-465337.js create mode 100644 js/src/tests/non262/extensions/regress-465443.js create mode 100644 js/src/tests/non262/extensions/regress-465453.js create mode 100644 js/src/tests/non262/extensions/regress-466905-04.js create mode 100644 js/src/tests/non262/extensions/regress-469234.js create mode 100644 js/src/tests/non262/extensions/regress-469405-01.js create mode 100644 js/src/tests/non262/extensions/regress-469405-02.js create mode 100644 js/src/tests/non262/extensions/regress-469625-01.js create mode 100644 js/src/tests/non262/extensions/regress-469625.js create mode 100644 js/src/tests/non262/extensions/regress-469761.js create mode 100644 js/src/tests/non262/extensions/regress-470300-01.js create mode 100644 js/src/tests/non262/extensions/regress-470300-02.js create mode 100644 js/src/tests/non262/extensions/regress-470310.js create mode 100644 js/src/tests/non262/extensions/regress-472450-03.js create mode 100644 js/src/tests/non262/extensions/regress-472450-04.js create mode 100644 js/src/tests/non262/extensions/regress-472599.js create mode 100644 js/src/tests/non262/extensions/regress-473040.js create mode 100644 js/src/tests/non262/extensions/regress-474771-01.js create mode 100644 js/src/tests/non262/extensions/regress-474771-02.js create mode 100644 js/src/tests/non262/extensions/regress-476414-01.js create mode 100644 js/src/tests/non262/extensions/regress-476414-02.js create mode 100644 js/src/tests/non262/extensions/regress-476447.js create mode 100644 js/src/tests/non262/extensions/regress-476653.js create mode 100644 js/src/tests/non262/extensions/regress-476869.js create mode 100644 js/src/tests/non262/extensions/regress-477158.js create mode 100644 js/src/tests/non262/extensions/regress-477187.js create mode 100644 js/src/tests/non262/extensions/regress-479487.js create mode 100644 js/src/tests/non262/extensions/regress-479551.js create mode 100644 js/src/tests/non262/extensions/regress-480579.js create mode 100644 js/src/tests/non262/extensions/regress-481516.js create mode 100644 js/src/tests/non262/extensions/regress-482263.js create mode 100644 js/src/tests/non262/extensions/regress-50447-1.js create mode 100644 js/src/tests/non262/extensions/regress-543839.js create mode 100644 js/src/tests/non262/extensions/regress-591450.js create mode 100644 js/src/tests/non262/extensions/regress-636818.js create mode 100644 js/src/tests/non262/extensions/regress-645160.js create mode 100644 js/src/tests/non262/extensions/regress-650753.js create mode 100644 js/src/tests/non262/extensions/regress-696109.js create mode 100644 js/src/tests/non262/extensions/regress-90596-001.js create mode 100644 js/src/tests/non262/extensions/regress-96284-001.js create mode 100644 js/src/tests/non262/extensions/regress-bug607284.js create mode 100644 js/src/tests/non262/extensions/regress-bug629723.js create mode 100644 js/src/tests/non262/extensions/reviver-mutates-holder-array-ccw.js create mode 100644 js/src/tests/non262/extensions/reviver-mutates-holder-array-nonnative.js create mode 100644 js/src/tests/non262/extensions/reviver-mutates-holder-array.js create mode 100644 js/src/tests/non262/extensions/reviver-mutates-holder-object-ccw.js create mode 100644 js/src/tests/non262/extensions/reviver-mutates-holder-object-nonnative.js create mode 100644 js/src/tests/non262/extensions/reviver-mutates-holder-object.js create mode 100644 js/src/tests/non262/extensions/scope-001.js create mode 100644 js/src/tests/non262/extensions/set-property-non-extensible.js create mode 100644 js/src/tests/non262/extensions/setImmutablePrototype.js create mode 100644 js/src/tests/non262/extensions/shareddataview.js create mode 100644 js/src/tests/non262/extensions/sharedtypedarray.js create mode 100644 js/src/tests/non262/extensions/shell.js create mode 100644 js/src/tests/non262/extensions/sps-generators.js create mode 100644 js/src/tests/non262/extensions/string-literal-getter-setter-decompilation.js create mode 100644 js/src/tests/non262/extensions/toLength.js create mode 100644 js/src/tests/non262/extensions/toLocaleString-infinite-recursion.js create mode 100644 js/src/tests/non262/extensions/toSource-infinite-recursion.js create mode 100644 js/src/tests/non262/extensions/too-many-arguments-constructing-bound-function.js create mode 100644 js/src/tests/non262/extensions/typedarray-copyWithin-arguments-detaching.js create mode 100644 js/src/tests/non262/extensions/typedarray-set-neutering.js create mode 100644 js/src/tests/non262/extensions/typedarray-subarray-of-subarray.js create mode 100644 js/src/tests/non262/extensions/typedarray.js create mode 100644 js/src/tests/non262/extensions/uneval/bug496985.js create mode 100644 js/src/tests/non262/extensions/uneval/bug566661.js create mode 100644 js/src/tests/non262/extensions/uneval/function-bind.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-231518.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-245795.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-254375.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-304897.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-306738.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-311583.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-313803.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-322957.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-328556.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-358594-01.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-358594-02.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-358594-03.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-358594-04.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-358594-05.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-358594-06.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-367629.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-375801.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-380581.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-380933.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-381211.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-381301.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-385393-03.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-385729.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-452498-082.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-452498-101.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-452498-117.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-621814.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-624199.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-90596-002.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-96284-002.js create mode 100644 js/src/tests/non262/extensions/uneval/regress-bug567606.js create mode 100644 js/src/tests/non262/extensions/uneval/symbol-uneval.js create mode 100644 js/src/tests/non262/extensions/uneval/toSource-0.js create mode 100644 js/src/tests/non262/extensions/unterminated-literal-error-location.js create mode 100644 js/src/tests/non262/extensions/weakmap.js create mode 100644 js/src/tests/non262/fields/await-identifier-module-1.js create mode 100644 js/src/tests/non262/fields/await-identifier-module-2.js create mode 100644 js/src/tests/non262/fields/await-identifier-module-3.js create mode 100644 js/src/tests/non262/fields/await-identifier-script.js create mode 100644 js/src/tests/non262/fields/browser.js create mode 100644 js/src/tests/non262/fields/bug1587574.js create mode 100644 js/src/tests/non262/fields/init-order.js create mode 100644 js/src/tests/non262/fields/numeric-fields.js create mode 100644 js/src/tests/non262/fields/scopes.js create mode 100644 js/src/tests/non262/fields/shell.js create mode 100644 js/src/tests/non262/fields/unimplemented.js create mode 100644 js/src/tests/non262/generators/326466-01.js create mode 100644 js/src/tests/non262/generators/browser.js create mode 100644 js/src/tests/non262/generators/construct-newtarget.js create mode 100644 js/src/tests/non262/generators/create-function-parse-before-getprototype.js create mode 100644 js/src/tests/non262/generators/delegating-yield-1.js create mode 100644 js/src/tests/non262/generators/delegating-yield-10.js create mode 100644 js/src/tests/non262/generators/delegating-yield-11.js create mode 100644 js/src/tests/non262/generators/delegating-yield-12.js create mode 100644 js/src/tests/non262/generators/delegating-yield-2.js create mode 100644 js/src/tests/non262/generators/delegating-yield-3.js create mode 100644 js/src/tests/non262/generators/delegating-yield-4.js create mode 100644 js/src/tests/non262/generators/delegating-yield-5.js create mode 100644 js/src/tests/non262/generators/delegating-yield-6.js create mode 100644 js/src/tests/non262/generators/delegating-yield-7.js create mode 100644 js/src/tests/non262/generators/delegating-yield-8.js create mode 100644 js/src/tests/non262/generators/delegating-yield-9.js create mode 100644 js/src/tests/non262/generators/fibonacci-matrix-generator.js create mode 100644 js/src/tests/non262/generators/forbidden-as-consequent.js create mode 100644 js/src/tests/non262/generators/gen-with-call-obj.js create mode 100644 js/src/tests/non262/generators/iteration.js create mode 100644 js/src/tests/non262/generators/iterator-next-non-object.js create mode 100644 js/src/tests/non262/generators/iterator-toString.js create mode 100644 js/src/tests/non262/generators/nested-yield.js create mode 100644 js/src/tests/non262/generators/objects.js create mode 100644 js/src/tests/non262/generators/pi-generator.js create mode 100644 js/src/tests/non262/generators/properties.js create mode 100644 js/src/tests/non262/generators/regress-345855.js create mode 100644 js/src/tests/non262/generators/regress-345879-01.js create mode 100644 js/src/tests/non262/generators/regress-349362.js create mode 100644 js/src/tests/non262/generators/regress-349851.js create mode 100644 js/src/tests/non262/generators/regress-350809.js create mode 100644 js/src/tests/non262/generators/regress-351120.js create mode 100644 js/src/tests/non262/generators/regress-359062.js create mode 100644 js/src/tests/non262/generators/regress-366941.js create mode 100644 js/src/tests/non262/generators/regress-384991.js create mode 100644 js/src/tests/non262/generators/regress-466206.js create mode 100644 js/src/tests/non262/generators/return-finally.js create mode 100644 js/src/tests/non262/generators/runtime.js create mode 100644 js/src/tests/non262/generators/shell.js create mode 100644 js/src/tests/non262/generators/simple-fib.js create mode 100644 js/src/tests/non262/generators/subclass.js create mode 100644 js/src/tests/non262/generators/syntax.js create mode 100644 js/src/tests/non262/generators/yield-error.js create mode 100644 js/src/tests/non262/generators/yield-iterator-close.js create mode 100644 js/src/tests/non262/generators/yield-non-regexp.js create mode 100644 js/src/tests/non262/generators/yield-star-iterator-close.js create mode 100644 js/src/tests/non262/generators/yield-star-iterator-primitive.js create mode 100644 js/src/tests/non262/generators/yield-star-throw-htmldda.js create mode 100644 js/src/tests/non262/get-set/browser.js create mode 100644 js/src/tests/non262/get-set/getset-002.js create mode 100644 js/src/tests/non262/get-set/regress-375976.js create mode 100644 js/src/tests/non262/get-set/shell.js create mode 100644 js/src/tests/non262/global/adding-global-var-nonextensible-error.js create mode 100644 js/src/tests/non262/global/browser.js create mode 100644 js/src/tests/non262/global/bug-320887.js create mode 100644 js/src/tests/non262/global/bug660612.js create mode 100644 js/src/tests/non262/global/cross-global-implicit-this.js create mode 100644 js/src/tests/non262/global/decodeURI-decodes-FFFE-FFFF.js create mode 100644 js/src/tests/non262/global/delete-global-NaN-property.js create mode 100644 js/src/tests/non262/global/direct-eval-but-not.js create mode 100644 js/src/tests/non262/global/eval-01.js create mode 100644 js/src/tests/non262/global/eval-02.js create mode 100644 js/src/tests/non262/global/eval-in-strict-eval-in-normal-function.js create mode 100644 js/src/tests/non262/global/eval-inside-with-is-direct.js create mode 100644 js/src/tests/non262/global/eval-native-callback-is-indirect.js create mode 100644 js/src/tests/non262/global/globalThis-enumeration.js create mode 100644 js/src/tests/non262/global/parenthesized-eval-is-direct.js create mode 100644 js/src/tests/non262/global/parseFloat-01.js create mode 100644 js/src/tests/non262/global/parseInt-01.js create mode 100644 js/src/tests/non262/global/parseInt-default-to-decimal.js create mode 100644 js/src/tests/non262/global/shell.js create mode 100644 js/src/tests/non262/iterable/browser.js create mode 100644 js/src/tests/non262/iterable/regress-340526-01.js create mode 100644 js/src/tests/non262/iterable/regress-341815.js create mode 100644 js/src/tests/non262/iterable/regress-341821.js create mode 100644 js/src/tests/non262/iterable/regress-415922.js create mode 100644 js/src/tests/non262/iterable/shell.js create mode 100644 js/src/tests/non262/jit/browser.js create mode 100644 js/src/tests/non262/jit/math-jit-tests.js create mode 100644 js/src/tests/non262/jit/regress-458838.js create mode 100644 js/src/tests/non262/jit/regress-489682.js create mode 100644 js/src/tests/non262/jit/shell.js create mode 100644 js/src/tests/non262/lexical-conventions/browser.js create mode 100644 js/src/tests/non262/lexical-conventions/lexical-001.js create mode 100644 js/src/tests/non262/lexical-conventions/regress-177314.js create mode 100644 js/src/tests/non262/lexical-conventions/regress-469940.js create mode 100644 js/src/tests/non262/lexical-conventions/shell.js create mode 100644 js/src/tests/non262/lexical-environment/block-scoped-functions-annex-b-arguments.js create mode 100644 js/src/tests/non262/lexical-environment/block-scoped-functions-annex-b-eval.js create mode 100644 js/src/tests/non262/lexical-environment/block-scoped-functions-annex-b-generators.js create mode 100644 js/src/tests/non262/lexical-environment/block-scoped-functions-annex-b-if.js create mode 100644 js/src/tests/non262/lexical-environment/block-scoped-functions-annex-b-label.js create mode 100644 js/src/tests/non262/lexical-environment/block-scoped-functions-annex-b-notapplicable.js create mode 100644 js/src/tests/non262/lexical-environment/block-scoped-functions-annex-b-parameter.js create mode 100644 js/src/tests/non262/lexical-environment/block-scoped-functions-annex-b-property.js create mode 100644 js/src/tests/non262/lexical-environment/block-scoped-functions-annex-b-same-name.js create mode 100644 js/src/tests/non262/lexical-environment/block-scoped-functions-annex-b-with.js create mode 100644 js/src/tests/non262/lexical-environment/block-scoped-functions-annex-b.js create mode 100644 js/src/tests/non262/lexical-environment/block-scoped-functions-deprecated-redecl.js create mode 100644 js/src/tests/non262/lexical-environment/block-scoped-functions-hoisted-tdz.js create mode 100644 js/src/tests/non262/lexical-environment/block-scoped-functions-strict.js create mode 100644 js/src/tests/non262/lexical-environment/browser.js create mode 100644 js/src/tests/non262/lexical-environment/bug-1216623.js create mode 100644 js/src/tests/non262/lexical-environment/catch-body.js create mode 100644 js/src/tests/non262/lexical-environment/const-declaration-in-for-loop.js create mode 100644 js/src/tests/non262/lexical-environment/eval-has-lexical-environment.js create mode 100644 js/src/tests/non262/lexical-environment/eval-nondefinable-function.js create mode 100644 js/src/tests/non262/lexical-environment/for-loop-with-bindings-added-at-runtime.js create mode 100644 js/src/tests/non262/lexical-environment/for-loop.js create mode 100644 js/src/tests/non262/lexical-environment/implicit-this-in-with.js create mode 100644 js/src/tests/non262/lexical-environment/nondefinable-function-same-script.js create mode 100644 js/src/tests/non262/lexical-environment/redeclaring-global-properties.js create mode 100644 js/src/tests/non262/lexical-environment/shell.js create mode 100644 js/src/tests/non262/lexical-environment/unscopables-basics.js create mode 100644 js/src/tests/non262/lexical-environment/unscopables-closures.js create mode 100644 js/src/tests/non262/lexical-environment/unscopables-const.js create mode 100644 js/src/tests/non262/lexical-environment/unscopables-delete.js create mode 100644 js/src/tests/non262/lexical-environment/unscopables-getters.js create mode 100644 js/src/tests/non262/lexical-environment/unscopables-global.js create mode 100644 js/src/tests/non262/lexical-environment/unscopables-ignored.js create mode 100644 js/src/tests/non262/lexical-environment/unscopables-miss.js create mode 100644 js/src/tests/non262/lexical-environment/unscopables-mutation-frozen.js create mode 100644 js/src/tests/non262/lexical-environment/unscopables-mutation.js create mode 100644 js/src/tests/non262/lexical-environment/unscopables-proto.js create mode 100644 js/src/tests/non262/lexical-environment/unscopables-proxy.js create mode 100644 js/src/tests/non262/lexical-environment/unscopables-strict.js create mode 100644 js/src/tests/non262/lexical-environment/unscopables-tdz.js create mode 100644 js/src/tests/non262/lexical-environment/var-in-catch-body-annex-b-eval-destructuring.js create mode 100644 js/src/tests/non262/lexical-environment/var-in-catch-body-annex-b-eval-for-of.js create mode 100644 js/src/tests/non262/lexical-environment/var-in-catch-body-annex-b-eval.js create mode 100644 js/src/tests/non262/lexical-environment/var-in-catch-body-annex-b.js create mode 100644 js/src/tests/non262/lexical-environment/with-global-ignores-global-let-variables.js create mode 100644 js/src/tests/non262/lexical/browser.js create mode 100644 js/src/tests/non262/lexical/regress-336376-01.js create mode 100644 js/src/tests/non262/lexical/regress-346642-04.js create mode 100644 js/src/tests/non262/lexical/regress-351515.js create mode 100644 js/src/tests/non262/lexical/shell.js create mode 100644 js/src/tests/non262/literals/numeric/idstart-after-numeric.js create mode 100644 js/src/tests/non262/literals/numeric/shell.js create mode 100644 js/src/tests/non262/literals/shell.js create mode 100644 js/src/tests/non262/misc/browser.js create mode 100644 js/src/tests/non262/misc/bug1126318.js create mode 100644 js/src/tests/non262/misc/builtin-methods-reject-null-undefined-this.js create mode 100644 js/src/tests/non262/misc/enumerate-undefined.js create mode 100644 js/src/tests/non262/misc/error-undefined-message.js create mode 100644 js/src/tests/non262/misc/explicit-undefined-optional-argument.js create mode 100644 js/src/tests/non262/misc/function-definition-eval.js create mode 100644 js/src/tests/non262/misc/function-definition-evaluate.js create mode 100644 js/src/tests/non262/misc/future-reserved-words.js create mode 100644 js/src/tests/non262/misc/getter-setter-outerize-this.js create mode 100644 js/src/tests/non262/misc/global-numeric-properties.js create mode 100644 js/src/tests/non262/misc/line-paragraph-separator-parse-as-lineterminator.js create mode 100644 js/src/tests/non262/misc/new-with-non-constructor.js create mode 100644 js/src/tests/non262/misc/redeclare-var-non-writable-property.js create mode 100644 js/src/tests/non262/misc/regexp-functions-with-undefined.js create mode 100644 js/src/tests/non262/misc/regress-bug632003.js create mode 100644 js/src/tests/non262/misc/shell.js create mode 100644 js/src/tests/non262/misc/syntax-error-end-of-for-head-part.js create mode 100644 js/src/tests/non262/misc/unicode-escaped-keyword.js create mode 100644 js/src/tests/non262/misc/unicode-identifier-1d17.js create mode 100644 js/src/tests/non262/misc/unicode-identifier-82f1.js create mode 100644 js/src/tests/non262/misc/unnamed-function.js create mode 100644 js/src/tests/non262/misc/unwrapped-no-such-method.js create mode 100644 js/src/tests/non262/module/await-restricted-nested.js create mode 100644 js/src/tests/non262/module/browser.js create mode 100644 js/src/tests/non262/module/bug1488117-empty.js create mode 100644 js/src/tests/non262/module/bug1488117-import-namespace.js create mode 100644 js/src/tests/non262/module/bug1488117.js create mode 100644 js/src/tests/non262/module/bug1689499-a.js create mode 100644 js/src/tests/non262/module/bug1689499-b.js create mode 100644 js/src/tests/non262/module/bug1689499-c.js create mode 100644 js/src/tests/non262/module/bug1689499-x.js create mode 100644 js/src/tests/non262/module/bug1689499.js create mode 100644 js/src/tests/non262/module/bug1693261-async.mjs create mode 100644 js/src/tests/non262/module/bug1693261-c1.mjs create mode 100644 js/src/tests/non262/module/bug1693261-c2.mjs create mode 100644 js/src/tests/non262/module/bug1693261-x.mjs create mode 100644 js/src/tests/non262/module/bug1693261.js create mode 100644 js/src/tests/non262/module/module-export-name-star.js create mode 100644 js/src/tests/non262/module/shell.js create mode 100644 js/src/tests/non262/object/15.2.3.12.js create mode 100644 js/src/tests/non262/object/15.2.3.14-01.js create mode 100644 js/src/tests/non262/object/15.2.3.3-01.js create mode 100644 js/src/tests/non262/object/15.2.3.4-01.js create mode 100644 js/src/tests/non262/object/15.2.3.4-02.js create mode 100644 js/src/tests/non262/object/15.2.3.4-03.js create mode 100644 js/src/tests/non262/object/15.2.3.4-04.js create mode 100644 js/src/tests/non262/object/15.2.3.5-01.js create mode 100644 js/src/tests/non262/object/15.2.3.6-define-over-method.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-01-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-02-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-03-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-04-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-05-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-06-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-07-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-08-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-09-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-10-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-11-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-12-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-13-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-14-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-15-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-16-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-17-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-18-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-19-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-20-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-21-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-22-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-23-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-24-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-25-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-26-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-27-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-28-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-29-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-30-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-31-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-dictionary-redefinition-32-of-32.js create mode 100644 js/src/tests/non262/object/15.2.3.6-function-length.js create mode 100644 js/src/tests/non262/object/15.2.3.6-middle-redefinition-1-of-8.js create mode 100644 js/src/tests/non262/object/15.2.3.6-middle-redefinition-2-of-8.js create mode 100644 js/src/tests/non262/object/15.2.3.6-middle-redefinition-3-of-8.js create mode 100644 js/src/tests/non262/object/15.2.3.6-middle-redefinition-4-of-8.js create mode 100644 js/src/tests/non262/object/15.2.3.6-middle-redefinition-5-of-8.js create mode 100644 js/src/tests/non262/object/15.2.3.6-middle-redefinition-6-of-8.js create mode 100644 js/src/tests/non262/object/15.2.3.6-middle-redefinition-7-of-8.js create mode 100644 js/src/tests/non262/object/15.2.3.6-middle-redefinition-8-of-8.js create mode 100644 js/src/tests/non262/object/15.2.3.6-miscellaneous.js create mode 100644 js/src/tests/non262/object/15.2.3.6-new-definition.js create mode 100644 js/src/tests/non262/object/15.2.3.6-redefinition-1-of-4.js create mode 100644 js/src/tests/non262/object/15.2.3.6-redefinition-2-of-4.js create mode 100644 js/src/tests/non262/object/15.2.3.6-redefinition-3-of-4.js create mode 100644 js/src/tests/non262/object/15.2.3.6-redefinition-4-of-4.js create mode 100644 js/src/tests/non262/object/15.2.3.7-01.js create mode 100644 js/src/tests/non262/object/15.2.3.9.js create mode 100644 js/src/tests/non262/object/accessor-arguments-rest.js create mode 100644 js/src/tests/non262/object/accessor-name.js create mode 100644 js/src/tests/non262/object/accessor-non-constructor.js create mode 100644 js/src/tests/non262/object/add-property-non-extensible.js create mode 100644 js/src/tests/non262/object/assign.js create mode 100644 js/src/tests/non262/object/browser.js create mode 100644 js/src/tests/non262/object/bug-1150906.js create mode 100644 js/src/tests/non262/object/bug-1206700.js create mode 100644 js/src/tests/non262/object/clear-dictionary-accessor-getset.js create mode 100644 js/src/tests/non262/object/defineGetter-defineSetter.js create mode 100644 js/src/tests/non262/object/defineProperties-callable-accessor.js create mode 100644 js/src/tests/non262/object/defineProperties-order.js create mode 100644 js/src/tests/non262/object/defineProperty-proxy.js create mode 100644 js/src/tests/non262/object/defineProperty-setup.js create mode 100644 js/src/tests/non262/object/destructuring-shorthand-defaults.js create mode 100644 js/src/tests/non262/object/duplProps.js create mode 100644 js/src/tests/non262/object/entries.js create mode 100644 js/src/tests/non262/object/extensibility-01.js create mode 100644 js/src/tests/non262/object/extensibility-02.js create mode 100644 js/src/tests/non262/object/freeze-global-eval-const.js create mode 100644 js/src/tests/non262/object/freeze-proxy.js create mode 100644 js/src/tests/non262/object/freeze.js create mode 100644 js/src/tests/non262/object/gOPD-vs-prototype-accessor.js create mode 100644 js/src/tests/non262/object/getOwnPropertyDescriptor.js create mode 100644 js/src/tests/non262/object/getOwnPropertySymbols-proxy.js create mode 100644 js/src/tests/non262/object/getOwnPropertySymbols.js create mode 100644 js/src/tests/non262/object/getPrototypeOf-array.js create mode 100644 js/src/tests/non262/object/getPrototypeOf.js create mode 100644 js/src/tests/non262/object/getter-name.js create mode 100644 js/src/tests/non262/object/hasOwn.js create mode 100644 js/src/tests/non262/object/isExtensible.js create mode 100644 js/src/tests/non262/object/isFrozen.js create mode 100644 js/src/tests/non262/object/isPrototypeOf.js create mode 100644 js/src/tests/non262/object/isSealed.js create mode 100644 js/src/tests/non262/object/keys.js create mode 100644 js/src/tests/non262/object/method-non-constructor.js create mode 100644 js/src/tests/non262/object/mutation-prevention-methods.js create mode 100644 js/src/tests/non262/object/object-create-with-primitive-second-arg.js create mode 100644 js/src/tests/non262/object/object-toString-01.js create mode 100644 js/src/tests/non262/object/preventExtensions-idempotent.js create mode 100644 js/src/tests/non262/object/preventExtensions-proxy.js create mode 100644 js/src/tests/non262/object/preventExtensions.js create mode 100644 js/src/tests/non262/object/property-descriptor-order.js create mode 100644 js/src/tests/non262/object/propertyIsEnumerable-proxy.js create mode 100644 js/src/tests/non262/object/propertyIsEnumerable.js create mode 100644 js/src/tests/non262/object/proto-property-change-writability-set.js create mode 100644 js/src/tests/non262/object/regress-137000.js create mode 100644 js/src/tests/non262/object/regress-192105.js create mode 100644 js/src/tests/non262/object/regress-308806-01.js create mode 100644 js/src/tests/non262/object/regress-338709.js create mode 100644 js/src/tests/non262/object/regress-361274.js create mode 100644 js/src/tests/non262/object/regress-382503.js create mode 100644 js/src/tests/non262/object/regress-382532.js create mode 100644 js/src/tests/non262/object/regress-385393-07.js create mode 100644 js/src/tests/non262/object/regress-444787.js create mode 100644 js/src/tests/non262/object/regress-459405.js create mode 100644 js/src/tests/non262/object/regress-465476.js create mode 100644 js/src/tests/non262/object/regress-72773.js create mode 100644 js/src/tests/non262/object/regress-79129-001.js create mode 100644 js/src/tests/non262/object/regress-90596-003.js create mode 100644 js/src/tests/non262/object/seal-proxy.js create mode 100644 js/src/tests/non262/object/seal.js create mode 100644 js/src/tests/non262/object/setPrototypeOf-cross-realm-cycle.js create mode 100644 js/src/tests/non262/object/setPrototypeOf-cycle.js create mode 100644 js/src/tests/non262/object/setPrototypeOf-same-value.js create mode 100644 js/src/tests/non262/object/shell.js create mode 100644 js/src/tests/non262/object/toLocaleString-01.js create mode 100644 js/src/tests/non262/object/toLocaleString.js create mode 100644 js/src/tests/non262/object/toPrimitive-callers.js create mode 100644 js/src/tests/non262/object/toPrimitive.js create mode 100644 js/src/tests/non262/object/vacuous-accessor-unqualified-name.js create mode 100644 js/src/tests/non262/object/values-entries-indexed.js create mode 100644 js/src/tests/non262/object/values-entries-lazy-props.js create mode 100644 js/src/tests/non262/object/values-entries-typedarray.js create mode 100644 js/src/tests/non262/object/values.js create mode 100644 js/src/tests/non262/operators/11.13.1-001.js create mode 100644 js/src/tests/non262/operators/11.13.1-002.js create mode 100644 js/src/tests/non262/operators/11.4.1-001.js create mode 100644 js/src/tests/non262/operators/11.4.1-002.js create mode 100644 js/src/tests/non262/operators/browser.js create mode 100644 js/src/tests/non262/operators/instanceof-bound-function-recursion.js create mode 100644 js/src/tests/non262/operators/order-01.js create mode 100644 js/src/tests/non262/operators/shell.js create mode 100644 js/src/tests/non262/reflect-parse/Match.js create mode 100644 js/src/tests/non262/reflect-parse/PatternAsserts.js create mode 100644 js/src/tests/non262/reflect-parse/PatternBuilders.js create mode 100644 js/src/tests/non262/reflect-parse/async.js create mode 100644 js/src/tests/non262/reflect-parse/browser.js create mode 100644 js/src/tests/non262/reflect-parse/class-fields.js create mode 100644 js/src/tests/non262/reflect-parse/class-static.js create mode 100644 js/src/tests/non262/reflect-parse/classes.js create mode 100644 js/src/tests/non262/reflect-parse/computedPropNames.js create mode 100644 js/src/tests/non262/reflect-parse/declarations.js create mode 100644 js/src/tests/non262/reflect-parse/destructuring-array-holes-reflect-as-null.js create mode 100644 js/src/tests/non262/reflect-parse/destructuring-assignment.js create mode 100644 js/src/tests/non262/reflect-parse/destructuring-function-parameters.js create mode 100644 js/src/tests/non262/reflect-parse/destructuring-variable-declarations.js create mode 100644 js/src/tests/non262/reflect-parse/destructuring__proto__.js create mode 100644 js/src/tests/non262/reflect-parse/expression-short-circuit-compound-assignment.js create mode 100644 js/src/tests/non262/reflect-parse/expression.js create mode 100644 js/src/tests/non262/reflect-parse/for-loop-destructuring.js create mode 100644 js/src/tests/non262/reflect-parse/generators.js create mode 100644 js/src/tests/non262/reflect-parse/lexicals.js create mode 100644 js/src/tests/non262/reflect-parse/location.js create mode 100644 js/src/tests/non262/reflect-parse/methodDefn.js create mode 100644 js/src/tests/non262/reflect-parse/module-export-name.js create mode 100644 js/src/tests/non262/reflect-parse/newTarget.js create mode 100644 js/src/tests/non262/reflect-parse/object-rest.js create mode 100644 js/src/tests/non262/reflect-parse/object-spread.js create mode 100644 js/src/tests/non262/reflect-parse/proxyArgs.js create mode 100644 js/src/tests/non262/reflect-parse/shell.js create mode 100644 js/src/tests/non262/reflect-parse/stackOverflow.js create mode 100644 js/src/tests/non262/reflect-parse/statements.js create mode 100644 js/src/tests/non262/reflect-parse/templateStrings.js create mode 100644 js/src/tests/non262/regress/browser.js create mode 100644 js/src/tests/non262/regress/regress-102725.js create mode 100644 js/src/tests/non262/regress/regress-10278.js create mode 100644 js/src/tests/non262/regress/regress-104077.js create mode 100644 js/src/tests/non262/regress/regress-110286.js create mode 100644 js/src/tests/non262/regress/regress-111557.js create mode 100644 js/src/tests/non262/regress/regress-114491.js create mode 100644 js/src/tests/non262/regress/regress-114493.js create mode 100644 js/src/tests/non262/regress/regress-116228.js create mode 100644 js/src/tests/non262/regress/regress-118849.js create mode 100644 js/src/tests/non262/regress/regress-131510-001.js create mode 100644 js/src/tests/non262/regress/regress-1383630.js create mode 100644 js/src/tests/non262/regress/regress-139316.js create mode 100644 js/src/tests/non262/regress/regress-140852.js create mode 100644 js/src/tests/non262/regress/regress-140974.js create mode 100644 js/src/tests/non262/regress/regress-1456512-greyreadbarrier.js create mode 100644 js/src/tests/non262/regress/regress-1456512.js create mode 100644 js/src/tests/non262/regress/regress-1456518-workergray.js create mode 100644 js/src/tests/non262/regress/regress-1463421.js create mode 100644 js/src/tests/non262/regress/regress-146596.js create mode 100644 js/src/tests/non262/regress/regress-1466387-worker-grayroot.js create mode 100644 js/src/tests/non262/regress/regress-1476383-calloc-exc.js create mode 100644 js/src/tests/non262/regress/regress-1507322-deep-weakmap.js create mode 100644 js/src/tests/non262/regress/regress-152646.js create mode 100644 js/src/tests/non262/regress/regress-155081-2.js create mode 100644 js/src/tests/non262/regress/regress-155081.js create mode 100644 js/src/tests/non262/regress/regress-156354.js create mode 100644 js/src/tests/non262/regress/regress-1572988-nurseryRegisterCheck.js create mode 100644 js/src/tests/non262/regress/regress-159334.js create mode 100644 js/src/tests/non262/regress/regress-162392.js create mode 100644 js/src/tests/non262/regress/regress-165201.js create mode 100644 js/src/tests/non262/regress/regress-167328.js create mode 100644 js/src/tests/non262/regress/regress-167658.js create mode 100644 js/src/tests/non262/regress/regress-168347.js create mode 100644 js/src/tests/non262/regress/regress-170193.js create mode 100644 js/src/tests/non262/regress/regress-1707974.js create mode 100644 js/src/tests/non262/regress/regress-1714532-oom-gc-yield.js create mode 100644 js/src/tests/non262/regress/regress-172699.js create mode 100644 js/src/tests/non262/regress/regress-174709.js create mode 100644 js/src/tests/non262/regress/regress-176125.js create mode 100644 js/src/tests/non262/regress/regress-179524.js create mode 100644 js/src/tests/non262/regress/regress-185165.js create mode 100644 js/src/tests/non262/regress/regress-191633.js create mode 100644 js/src/tests/non262/regress/regress-191668.js create mode 100644 js/src/tests/non262/regress/regress-192414.js create mode 100644 js/src/tests/non262/regress/regress-193418.js create mode 100644 js/src/tests/non262/regress/regress-203278-1.js create mode 100644 js/src/tests/non262/regress/regress-203402.js create mode 100644 js/src/tests/non262/regress/regress-203841.js create mode 100644 js/src/tests/non262/regress/regress-204210.js create mode 100644 js/src/tests/non262/regress/regress-210682.js create mode 100644 js/src/tests/non262/regress/regress-211590.js create mode 100644 js/src/tests/non262/regress/regress-214761.js create mode 100644 js/src/tests/non262/regress/regress-216320.js create mode 100644 js/src/tests/non262/regress/regress-224956.js create mode 100644 js/src/tests/non262/regress/regress-229006.js create mode 100644 js/src/tests/non262/regress/regress-230216-1.js create mode 100644 js/src/tests/non262/regress/regress-230216-2.js create mode 100644 js/src/tests/non262/regress/regress-230216-3.js create mode 100644 js/src/tests/non262/regress/regress-233483-2.js create mode 100644 js/src/tests/non262/regress/regress-233483.js create mode 100644 js/src/tests/non262/regress/regress-234389.js create mode 100644 js/src/tests/non262/regress/regress-238881.js create mode 100644 js/src/tests/non262/regress/regress-238945.js create mode 100644 js/src/tests/non262/regress/regress-243174.js create mode 100644 js/src/tests/non262/regress/regress-243389-n.js create mode 100644 js/src/tests/non262/regress/regress-243869.js create mode 100644 js/src/tests/non262/regress/regress-244470.js create mode 100644 js/src/tests/non262/regress/regress-244619.js create mode 100644 js/src/tests/non262/regress/regress-245113.js create mode 100644 js/src/tests/non262/regress/regress-245308.js create mode 100644 js/src/tests/non262/regress/regress-246911.js create mode 100644 js/src/tests/non262/regress/regress-246964.js create mode 100644 js/src/tests/non262/regress/regress-247179.js create mode 100644 js/src/tests/non262/regress/regress-248444.js create mode 100644 js/src/tests/non262/regress/regress-252892.js create mode 100644 js/src/tests/non262/regress/regress-254296.js create mode 100644 js/src/tests/non262/regress/regress-254974.js create mode 100644 js/src/tests/non262/regress/regress-256501.js create mode 100644 js/src/tests/non262/regress/regress-256617.js create mode 100644 js/src/tests/non262/regress/regress-256798.js create mode 100644 js/src/tests/non262/regress/regress-259935.js create mode 100644 js/src/tests/non262/regress/regress-260541.js create mode 100644 js/src/tests/non262/regress/regress-261886.js create mode 100644 js/src/tests/non262/regress/regress-261887.js create mode 100644 js/src/tests/non262/regress/regress-271716-n.js create mode 100644 js/src/tests/non262/regress/regress-274035.js create mode 100644 js/src/tests/non262/regress/regress-274888.js create mode 100644 js/src/tests/non262/regress/regress-275378.js create mode 100644 js/src/tests/non262/regress/regress-276103.js create mode 100644 js/src/tests/non262/regress/regress-278873.js create mode 100644 js/src/tests/non262/regress/regress-280769-1.js create mode 100644 js/src/tests/non262/regress/regress-280769-2.js create mode 100644 js/src/tests/non262/regress/regress-280769-3.js create mode 100644 js/src/tests/non262/regress/regress-280769-4.js create mode 100644 js/src/tests/non262/regress/regress-280769-5.js create mode 100644 js/src/tests/non262/regress/regress-280769.js create mode 100644 js/src/tests/non262/regress/regress-281606.js create mode 100644 js/src/tests/non262/regress/regress-281930.js create mode 100644 js/src/tests/non262/regress/regress-283477.js create mode 100644 js/src/tests/non262/regress/regress-288688.js create mode 100644 js/src/tests/non262/regress/regress-289094.js create mode 100644 js/src/tests/non262/regress/regress-290575.js create mode 100644 js/src/tests/non262/regress/regress-290656.js create mode 100644 js/src/tests/non262/regress/regress-294191.js create mode 100644 js/src/tests/non262/regress/regress-294195-01.js create mode 100644 js/src/tests/non262/regress/regress-294195-02.js create mode 100644 js/src/tests/non262/regress/regress-294302.js create mode 100644 js/src/tests/non262/regress/regress-295052.js create mode 100644 js/src/tests/non262/regress/regress-295666.js create mode 100644 js/src/tests/non262/regress/regress-299209.js create mode 100644 js/src/tests/non262/regress/regress-299641.js create mode 100644 js/src/tests/non262/regress/regress-303213.js create mode 100644 js/src/tests/non262/regress/regress-306633.js create mode 100644 js/src/tests/non262/regress/regress-306794.js create mode 100644 js/src/tests/non262/regress/regress-308085.js create mode 100644 js/src/tests/non262/regress/regress-310295.js create mode 100644 js/src/tests/non262/regress/regress-310607.js create mode 100644 js/src/tests/non262/regress/regress-310993.js create mode 100644 js/src/tests/non262/regress/regress-311071.js create mode 100644 js/src/tests/non262/regress/regress-311157-01.js create mode 100644 js/src/tests/non262/regress/regress-311157-02.js create mode 100644 js/src/tests/non262/regress/regress-311629.js create mode 100644 js/src/tests/non262/regress/regress-31255.js create mode 100644 js/src/tests/non262/regress/regress-312588.js create mode 100644 js/src/tests/non262/regress/regress-314401.js create mode 100644 js/src/tests/non262/regress/regress-315990.js create mode 100644 js/src/tests/non262/regress/regress-317476.js create mode 100644 js/src/tests/non262/regress/regress-317714-01.js create mode 100644 js/src/tests/non262/regress/regress-317714-02.js create mode 100644 js/src/tests/non262/regress/regress-319384.js create mode 100644 js/src/tests/non262/regress/regress-319391.js create mode 100644 js/src/tests/non262/regress/regress-320032.js create mode 100644 js/src/tests/non262/regress/regress-320172.js create mode 100644 js/src/tests/non262/regress/regress-321757.js create mode 100644 js/src/tests/non262/regress/regress-321874.js create mode 100644 js/src/tests/non262/regress/regress-321971.js create mode 100644 js/src/tests/non262/regress/regress-325925.js create mode 100644 js/src/tests/non262/regress/regress-326467.js create mode 100644 js/src/tests/non262/regress/regress-328012.js create mode 100644 js/src/tests/non262/regress/regress-328664.js create mode 100644 js/src/tests/non262/regress/regress-329383.js create mode 100644 js/src/tests/non262/regress/regress-329530.js create mode 100644 js/src/tests/non262/regress/regress-330352.js create mode 100644 js/src/tests/non262/regress/regress-330951.js create mode 100644 js/src/tests/non262/regress/regress-334807-01.js create mode 100644 js/src/tests/non262/regress/regress-334807-02.js create mode 100644 js/src/tests/non262/regress/regress-334807-03.js create mode 100644 js/src/tests/non262/regress/regress-334807-04.js create mode 100644 js/src/tests/non262/regress/regress-334807-05.js create mode 100644 js/src/tests/non262/regress/regress-334807-06.js create mode 100644 js/src/tests/non262/regress/regress-336100.js create mode 100644 js/src/tests/non262/regress/regress-338307.js create mode 100644 js/src/tests/non262/regress/regress-340369.js create mode 100644 js/src/tests/non262/regress/regress-341360.js create mode 100644 js/src/tests/non262/regress/regress-343713.js create mode 100644 js/src/tests/non262/regress/regress-343966.js create mode 100644 js/src/tests/non262/regress/regress-344711-n.js create mode 100644 js/src/tests/non262/regress/regress-344804.js create mode 100644 js/src/tests/non262/regress/regress-344959.js create mode 100644 js/src/tests/non262/regress/regress-346237.js create mode 100644 js/src/tests/non262/regress/regress-346801.js create mode 100644 js/src/tests/non262/regress/regress-349482-01.js create mode 100644 js/src/tests/non262/regress/regress-349482-02.js create mode 100644 js/src/tests/non262/regress/regress-349592.js create mode 100644 js/src/tests/non262/regress/regress-350253.js create mode 100644 js/src/tests/non262/regress/regress-350268.js create mode 100644 js/src/tests/non262/regress/regress-350312.js create mode 100644 js/src/tests/non262/regress/regress-350415.js create mode 100644 js/src/tests/non262/regress/regress-350529.js create mode 100644 js/src/tests/non262/regress/regress-351116.js create mode 100644 js/src/tests/non262/regress/regress-351515.js create mode 100644 js/src/tests/non262/regress/regress-351795.js create mode 100644 js/src/tests/non262/regress/regress-352208.js create mode 100644 js/src/tests/non262/regress/regress-352604.js create mode 100644 js/src/tests/non262/regress/regress-352640-01.js create mode 100644 js/src/tests/non262/regress/regress-352640-02.js create mode 100644 js/src/tests/non262/regress/regress-352640-04.js create mode 100644 js/src/tests/non262/regress/regress-353078.js create mode 100644 js/src/tests/non262/regress/regress-353079.js create mode 100644 js/src/tests/non262/regress/regress-355023.js create mode 100644 js/src/tests/non262/regress/regress-355556.js create mode 100644 js/src/tests/non262/regress/regress-355569.js create mode 100644 js/src/tests/non262/regress/regress-355829-01.js create mode 100644 js/src/tests/non262/regress/regress-355829-02.js create mode 100644 js/src/tests/non262/regress/regress-355829-03.js create mode 100644 js/src/tests/non262/regress/regress-355832-01.js create mode 100644 js/src/tests/non262/regress/regress-355832-02.js create mode 100644 js/src/tests/non262/regress/regress-356250.js create mode 100644 js/src/tests/non262/regress/regress-356693.js create mode 100644 js/src/tests/non262/regress/regress-360969-01.js create mode 100644 js/src/tests/non262/regress/regress-360969-02.js create mode 100644 js/src/tests/non262/regress/regress-360969-03.js create mode 100644 js/src/tests/non262/regress/regress-360969-04.js create mode 100644 js/src/tests/non262/regress/regress-360969-05.js create mode 100644 js/src/tests/non262/regress/regress-360969-06.js create mode 100644 js/src/tests/non262/regress/regress-363040-01.js create mode 100644 js/src/tests/non262/regress/regress-363040-02.js create mode 100644 js/src/tests/non262/regress/regress-3649-n.js create mode 100644 js/src/tests/non262/regress/regress-366122.js create mode 100644 js/src/tests/non262/regress/regress-366468.js create mode 100644 js/src/tests/non262/regress/regress-366601.js create mode 100644 js/src/tests/non262/regress/regress-367561-01.js create mode 100644 js/src/tests/non262/regress/regress-367561-03.js create mode 100644 js/src/tests/non262/regress/regress-369666-01.js create mode 100644 js/src/tests/non262/regress/regress-369666-02.js create mode 100644 js/src/tests/non262/regress/regress-372364.js create mode 100644 js/src/tests/non262/regress/regress-373827-01.js create mode 100644 js/src/tests/non262/regress/regress-373827-02.js create mode 100644 js/src/tests/non262/regress/regress-373843.js create mode 100644 js/src/tests/non262/regress/regress-379245.js create mode 100644 js/src/tests/non262/regress/regress-379442.js create mode 100644 js/src/tests/non262/regress/regress-379483.js create mode 100644 js/src/tests/non262/regress/regress-383674.js create mode 100644 js/src/tests/non262/regress/regress-383682.js create mode 100644 js/src/tests/non262/regress/regress-383902.js create mode 100644 js/src/tests/non262/regress/regress-385393-04.js create mode 100644 js/src/tests/non262/regress/regress-387951-01.js create mode 100644 js/src/tests/non262/regress/regress-387951-02.js create mode 100644 js/src/tests/non262/regress/regress-387951-03.js create mode 100644 js/src/tests/non262/regress/regress-39309.js create mode 100644 js/src/tests/non262/regress/regress-396684.js create mode 100644 js/src/tests/non262/regress/regress-398085-01.js create mode 100644 js/src/tests/non262/regress/regress-398085-02.js create mode 100644 js/src/tests/non262/regress/regress-398609.js create mode 100644 js/src/tests/non262/regress/regress-404734.js create mode 100644 js/src/tests/non262/regress/regress-404755.js create mode 100644 js/src/tests/non262/regress/regress-406769.js create mode 100644 js/src/tests/non262/regress/regress-407024.js create mode 100644 js/src/tests/non262/regress/regress-407727-01.js create mode 100644 js/src/tests/non262/regress/regress-407727-02.js create mode 100644 js/src/tests/non262/regress/regress-410649.js create mode 100644 js/src/tests/non262/regress/regress-410852.js create mode 100644 js/src/tests/non262/regress/regress-414553.js create mode 100644 js/src/tests/non262/regress/regress-416737-01.js create mode 100644 js/src/tests/non262/regress/regress-416737-02.js create mode 100644 js/src/tests/non262/regress/regress-417893.js create mode 100644 js/src/tests/non262/regress/regress-418540.js create mode 100644 js/src/tests/non262/regress/regress-418641.js create mode 100644 js/src/tests/non262/regress/regress-419018.js create mode 100644 js/src/tests/non262/regress/regress-419152.js create mode 100644 js/src/tests/non262/regress/regress-419803.js create mode 100644 js/src/tests/non262/regress/regress-420087.js create mode 100644 js/src/tests/non262/regress/regress-420610.js create mode 100644 js/src/tests/non262/regress/regress-420919.js create mode 100644 js/src/tests/non262/regress/regress-422348.js create mode 100644 js/src/tests/non262/regress/regress-424311.js create mode 100644 js/src/tests/non262/regress/regress-425360.js create mode 100644 js/src/tests/non262/regress/regress-426827.js create mode 100644 js/src/tests/non262/regress/regress-427798.js create mode 100644 js/src/tests/non262/regress/regress-428366.js create mode 100644 js/src/tests/non262/regress/regress-433279-01.js create mode 100644 js/src/tests/non262/regress/regress-433279-02.js create mode 100644 js/src/tests/non262/regress/regress-433279-03.js create mode 100644 js/src/tests/non262/regress/regress-438415-01.js create mode 100644 js/src/tests/non262/regress/regress-438415-02.js create mode 100644 js/src/tests/non262/regress/regress-440926.js create mode 100644 js/src/tests/non262/regress/regress-441477-01.js create mode 100644 js/src/tests/non262/regress/regress-442333-01.js create mode 100644 js/src/tests/non262/regress/regress-449627.js create mode 100644 js/src/tests/non262/regress/regress-449666.js create mode 100644 js/src/tests/non262/regress/regress-450369.js create mode 100644 js/src/tests/non262/regress/regress-450833.js create mode 100644 js/src/tests/non262/regress/regress-451322.js create mode 100644 js/src/tests/non262/regress/regress-451884.js create mode 100644 js/src/tests/non262/regress/regress-451946.js create mode 100644 js/src/tests/non262/regress/regress-452008.js create mode 100644 js/src/tests/non262/regress/regress-452170.js create mode 100644 js/src/tests/non262/regress/regress-452189.js create mode 100644 js/src/tests/non262/regress/regress-452333.js create mode 100644 js/src/tests/non262/regress/regress-452336.js create mode 100644 js/src/tests/non262/regress/regress-452346.js create mode 100644 js/src/tests/non262/regress/regress-452491.js create mode 100644 js/src/tests/non262/regress/regress-452495.js create mode 100644 js/src/tests/non262/regress/regress-452498-006.js create mode 100644 js/src/tests/non262/regress/regress-452498-027.js create mode 100644 js/src/tests/non262/regress/regress-452498-030.js create mode 100644 js/src/tests/non262/regress/regress-452498-040.js create mode 100644 js/src/tests/non262/regress/regress-452498-050.js create mode 100644 js/src/tests/non262/regress/regress-452498-051.js create mode 100644 js/src/tests/non262/regress/regress-452498-052-a.js create mode 100644 js/src/tests/non262/regress/regress-452498-053.js create mode 100644 js/src/tests/non262/regress/regress-452498-058.js create mode 100644 js/src/tests/non262/regress/regress-452498-062.js create mode 100644 js/src/tests/non262/regress/regress-452498-063.js create mode 100644 js/src/tests/non262/regress/regress-452498-071.js create mode 100644 js/src/tests/non262/regress/regress-452498-072.js create mode 100644 js/src/tests/non262/regress/regress-452498-073.js create mode 100644 js/src/tests/non262/regress/regress-452498-074.js create mode 100644 js/src/tests/non262/regress/regress-452498-075.js create mode 100644 js/src/tests/non262/regress/regress-452498-076.js create mode 100644 js/src/tests/non262/regress/regress-452498-079.js create mode 100644 js/src/tests/non262/regress/regress-452498-082.js create mode 100644 js/src/tests/non262/regress/regress-452498-092.js create mode 100644 js/src/tests/non262/regress/regress-452498-102.js create mode 100644 js/src/tests/non262/regress/regress-452498-104.js create mode 100644 js/src/tests/non262/regress/regress-452498-111.js create mode 100644 js/src/tests/non262/regress/regress-452498-112.js create mode 100644 js/src/tests/non262/regress/regress-452498-114-a.js create mode 100644 js/src/tests/non262/regress/regress-452498-114.js create mode 100644 js/src/tests/non262/regress/regress-452498-116.js create mode 100644 js/src/tests/non262/regress/regress-452498-117.js create mode 100644 js/src/tests/non262/regress/regress-452498-118.js create mode 100644 js/src/tests/non262/regress/regress-452498-121.js create mode 100644 js/src/tests/non262/regress/regress-452498-123.js create mode 100644 js/src/tests/non262/regress/regress-452498-129.js create mode 100644 js/src/tests/non262/regress/regress-452498-131.js create mode 100644 js/src/tests/non262/regress/regress-452498-135.js create mode 100644 js/src/tests/non262/regress/regress-452498-155.js create mode 100644 js/src/tests/non262/regress/regress-452498-160.js create mode 100644 js/src/tests/non262/regress/regress-452498-168-1.js create mode 100644 js/src/tests/non262/regress/regress-452498-168-2.js create mode 100644 js/src/tests/non262/regress/regress-452498-176.js create mode 100644 js/src/tests/non262/regress/regress-452498-181.js create mode 100644 js/src/tests/non262/regress/regress-452498-185.js create mode 100644 js/src/tests/non262/regress/regress-452498-187.js create mode 100644 js/src/tests/non262/regress/regress-452498-191.js create mode 100644 js/src/tests/non262/regress/regress-452498-192.js create mode 100644 js/src/tests/non262/regress/regress-452573-01.js create mode 100644 js/src/tests/non262/regress/regress-452573-02.js create mode 100644 js/src/tests/non262/regress/regress-452703.js create mode 100644 js/src/tests/non262/regress/regress-452713.js create mode 100644 js/src/tests/non262/regress/regress-452724-01.js create mode 100644 js/src/tests/non262/regress/regress-452724-02.js create mode 100644 js/src/tests/non262/regress/regress-452742-01.js create mode 100644 js/src/tests/non262/regress/regress-452742-02.js create mode 100644 js/src/tests/non262/regress/regress-452853.js create mode 100644 js/src/tests/non262/regress/regress-452884-01.js create mode 100644 js/src/tests/non262/regress/regress-452884-02.js create mode 100644 js/src/tests/non262/regress/regress-452960.js create mode 100644 js/src/tests/non262/regress/regress-453024.js create mode 100644 js/src/tests/non262/regress/regress-453049.js create mode 100644 js/src/tests/non262/regress/regress-453051.js create mode 100644 js/src/tests/non262/regress/regress-453173.js create mode 100644 js/src/tests/non262/regress/regress-453397.js create mode 100644 js/src/tests/non262/regress/regress-453701.js create mode 100644 js/src/tests/non262/regress/regress-453747.js create mode 100644 js/src/tests/non262/regress/regress-454682.js create mode 100644 js/src/tests/non262/regress/regress-454981.js create mode 100644 js/src/tests/non262/regress/regress-455605.js create mode 100644 js/src/tests/non262/regress/regress-455748.js create mode 100644 js/src/tests/non262/regress/regress-455758-01.js create mode 100644 js/src/tests/non262/regress/regress-455758-02.js create mode 100644 js/src/tests/non262/regress/regress-455775.js create mode 100644 js/src/tests/non262/regress/regress-455981-01.js create mode 100644 js/src/tests/non262/regress/regress-455981-02.js create mode 100644 js/src/tests/non262/regress/regress-456470.js create mode 100644 js/src/tests/non262/regress/regress-456477-01.js create mode 100644 js/src/tests/non262/regress/regress-456477-02.js create mode 100644 js/src/tests/non262/regress/regress-456494.js create mode 100644 js/src/tests/non262/regress/regress-456540-01.js create mode 100644 js/src/tests/non262/regress/regress-456540-02.js create mode 100644 js/src/tests/non262/regress/regress-457065-01.js create mode 100644 js/src/tests/non262/regress/regress-457065-02.js create mode 100644 js/src/tests/non262/regress/regress-457065-03.js create mode 100644 js/src/tests/non262/regress/regress-457456.js create mode 100644 js/src/tests/non262/regress/regress-457778.js create mode 100644 js/src/tests/non262/regress/regress-458076.js create mode 100644 js/src/tests/non262/regress/regress-458851.js create mode 100644 js/src/tests/non262/regress/regress-459085.js create mode 100644 js/src/tests/non262/regress/regress-459185.js create mode 100644 js/src/tests/non262/regress/regress-459186.js create mode 100644 js/src/tests/non262/regress/regress-459389.js create mode 100644 js/src/tests/non262/regress/regress-459628.js create mode 100644 js/src/tests/non262/regress/regress-459990.js create mode 100644 js/src/tests/non262/regress/regress-460024.js create mode 100644 js/src/tests/non262/regress/regress-460117.js create mode 100644 js/src/tests/non262/regress/regress-460886-01.js create mode 100644 js/src/tests/non262/regress/regress-460886-02.js create mode 100644 js/src/tests/non262/regress/regress-461307.js create mode 100644 js/src/tests/non262/regress/regress-461723.js create mode 100644 js/src/tests/non262/regress/regress-462071.js create mode 100644 js/src/tests/non262/regress/regress-462282.js create mode 100644 js/src/tests/non262/regress/regress-462292.js create mode 100644 js/src/tests/non262/regress/regress-462388.js create mode 100644 js/src/tests/non262/regress/regress-462407.js create mode 100644 js/src/tests/non262/regress/regress-462879.js create mode 100644 js/src/tests/non262/regress/regress-462989.js create mode 100644 js/src/tests/non262/regress/regress-463259.js create mode 100644 js/src/tests/non262/regress/regress-463782.js create mode 100644 js/src/tests/non262/regress/regress-464096.js create mode 100644 js/src/tests/non262/regress/regress-464334.js create mode 100644 js/src/tests/non262/regress/regress-464403.js create mode 100644 js/src/tests/non262/regress/regress-464418.js create mode 100644 js/src/tests/non262/regress/regress-464862.js create mode 100644 js/src/tests/non262/regress/regress-464978.js create mode 100644 js/src/tests/non262/regress/regress-465013.js create mode 100644 js/src/tests/non262/regress/regress-465132.js create mode 100644 js/src/tests/non262/regress/regress-465133.js create mode 100644 js/src/tests/non262/regress/regress-465135.js create mode 100644 js/src/tests/non262/regress/regress-465136.js create mode 100644 js/src/tests/non262/regress/regress-465137.js create mode 100644 js/src/tests/non262/regress/regress-465220.js create mode 100644 js/src/tests/non262/regress/regress-465234.js create mode 100644 js/src/tests/non262/regress/regress-465236.js create mode 100644 js/src/tests/non262/regress/regress-465239.js create mode 100644 js/src/tests/non262/regress/regress-465241.js create mode 100644 js/src/tests/non262/regress/regress-465249.js create mode 100644 js/src/tests/non262/regress/regress-465261.js create mode 100644 js/src/tests/non262/regress/regress-465262.js create mode 100644 js/src/tests/non262/regress/regress-465272.js create mode 100644 js/src/tests/non262/regress/regress-465308.js create mode 100644 js/src/tests/non262/regress/regress-465347.js create mode 100644 js/src/tests/non262/regress/regress-465366.js create mode 100644 js/src/tests/non262/regress/regress-465424.js create mode 100644 js/src/tests/non262/regress/regress-465454.js create mode 100644 js/src/tests/non262/regress/regress-465460-01.js create mode 100644 js/src/tests/non262/regress/regress-465460-02.js create mode 100644 js/src/tests/non262/regress/regress-465460-03.js create mode 100644 js/src/tests/non262/regress/regress-465460-04.js create mode 100644 js/src/tests/non262/regress/regress-465460-05.js create mode 100644 js/src/tests/non262/regress/regress-465460-06.js create mode 100644 js/src/tests/non262/regress/regress-465460-07.js create mode 100644 js/src/tests/non262/regress/regress-465460-08.js create mode 100644 js/src/tests/non262/regress/regress-465460-10.js create mode 100644 js/src/tests/non262/regress/regress-465460-11.js create mode 100644 js/src/tests/non262/regress/regress-465460-12.js create mode 100644 js/src/tests/non262/regress/regress-465483.js create mode 100644 js/src/tests/non262/regress/regress-465484.js create mode 100644 js/src/tests/non262/regress/regress-465567-01.js create mode 100644 js/src/tests/non262/regress/regress-465567-02.js create mode 100644 js/src/tests/non262/regress/regress-465686.js create mode 100644 js/src/tests/non262/regress/regress-465688.js create mode 100644 js/src/tests/non262/regress/regress-466128.js create mode 100644 js/src/tests/non262/regress/regress-466262.js create mode 100644 js/src/tests/non262/regress/regress-466747.js create mode 100644 js/src/tests/non262/regress/regress-466787.js create mode 100644 js/src/tests/non262/regress/regress-466905-01.js create mode 100644 js/src/tests/non262/regress/regress-466905-02.js create mode 100644 js/src/tests/non262/regress/regress-467495-01.js create mode 100644 js/src/tests/non262/regress/regress-467495-02.js create mode 100644 js/src/tests/non262/regress/regress-467495-03.js create mode 100644 js/src/tests/non262/regress/regress-467495-04.js create mode 100644 js/src/tests/non262/regress/regress-467495-05.js create mode 100644 js/src/tests/non262/regress/regress-467495-06.js create mode 100644 js/src/tests/non262/regress/regress-468711.js create mode 100644 js/src/tests/non262/regress/regress-469044.js create mode 100644 js/src/tests/non262/regress/regress-469239-01.js create mode 100644 js/src/tests/non262/regress/regress-469239-02.js create mode 100644 js/src/tests/non262/regress/regress-469547.js create mode 100644 js/src/tests/non262/regress/regress-469625-02.js create mode 100644 js/src/tests/non262/regress/regress-469625-03.js create mode 100644 js/src/tests/non262/regress/regress-469758.js create mode 100644 js/src/tests/non262/regress/regress-469937.js create mode 100644 js/src/tests/non262/regress/regress-470061.js create mode 100644 js/src/tests/non262/regress/regress-470187-01.js create mode 100644 js/src/tests/non262/regress/regress-470187-02.js create mode 100644 js/src/tests/non262/regress/regress-470223.js create mode 100644 js/src/tests/non262/regress/regress-470388-01.js create mode 100644 js/src/tests/non262/regress/regress-470758-01.js create mode 100644 js/src/tests/non262/regress/regress-470758-02.js create mode 100644 js/src/tests/non262/regress/regress-471660.js create mode 100644 js/src/tests/non262/regress/regress-472533.js create mode 100644 js/src/tests/non262/regress/regress-474769.js create mode 100644 js/src/tests/non262/regress/regress-474771-01.js create mode 100644 js/src/tests/non262/regress/regress-474771.js create mode 100644 js/src/tests/non262/regress/regress-474935.js create mode 100644 js/src/tests/non262/regress/regress-475469.js create mode 100644 js/src/tests/non262/regress/regress-475645-01.js create mode 100644 js/src/tests/non262/regress/regress-475645-02.js create mode 100644 js/src/tests/non262/regress/regress-476049.js create mode 100644 js/src/tests/non262/regress/regress-476192.js create mode 100644 js/src/tests/non262/regress/regress-476655.js create mode 100644 js/src/tests/non262/regress/regress-477053.js create mode 100644 js/src/tests/non262/regress/regress-477234.js create mode 100644 js/src/tests/non262/regress/regress-477733.js create mode 100644 js/src/tests/non262/regress/regress-477758.js create mode 100644 js/src/tests/non262/regress/regress-478205.js create mode 100644 js/src/tests/non262/regress/regress-478314.js create mode 100644 js/src/tests/non262/regress/regress-479353-01.js create mode 100644 js/src/tests/non262/regress/regress-479353.js create mode 100644 js/src/tests/non262/regress/regress-479430-01.js create mode 100644 js/src/tests/non262/regress/regress-479430-02.js create mode 100644 js/src/tests/non262/regress/regress-479430-03.js create mode 100644 js/src/tests/non262/regress/regress-479430-04.js create mode 100644 js/src/tests/non262/regress/regress-479430-05.js create mode 100644 js/src/tests/non262/regress/regress-479740.js create mode 100644 js/src/tests/non262/regress/regress-480147.js create mode 100644 js/src/tests/non262/regress/regress-480244.js create mode 100644 js/src/tests/non262/regress/regress-481436.js create mode 100644 js/src/tests/non262/regress/regress-481800.js create mode 100644 js/src/tests/non262/regress/regress-482421.js create mode 100644 js/src/tests/non262/regress/regress-482783.js create mode 100644 js/src/tests/non262/regress/regress-483103.js create mode 100644 js/src/tests/non262/regress/regress-483749.js create mode 100644 js/src/tests/non262/regress/regress-495773.js create mode 100644 js/src/tests/non262/regress/regress-495907.js create mode 100644 js/src/tests/non262/regress/regress-496922.js create mode 100644 js/src/tests/non262/regress/regress-499524.js create mode 100644 js/src/tests/non262/regress/regress-500528.js create mode 100644 js/src/tests/non262/regress/regress-501124.js create mode 100644 js/src/tests/non262/regress/regress-503860.js create mode 100644 js/src/tests/non262/regress/regress-504078.js create mode 100644 js/src/tests/non262/regress/regress-507053.js create mode 100644 js/src/tests/non262/regress/regress-507295.js create mode 100644 js/src/tests/non262/regress/regress-509354.js create mode 100644 js/src/tests/non262/regress/regress-511859.js create mode 100644 js/src/tests/non262/regress/regress-522123.js create mode 100644 js/src/tests/non262/regress/regress-524743.js create mode 100644 js/src/tests/non262/regress/regress-530879.js create mode 100644 js/src/tests/non262/regress/regress-532491.js create mode 100644 js/src/tests/non262/regress/regress-541255-3.js create mode 100644 js/src/tests/non262/regress/regress-541455.js create mode 100644 js/src/tests/non262/regress/regress-551763-0.js create mode 100644 js/src/tests/non262/regress/regress-551763-1.js create mode 100644 js/src/tests/non262/regress/regress-551763-2.js create mode 100644 js/src/tests/non262/regress/regress-552432.js create mode 100644 js/src/tests/non262/regress/regress-553778.js create mode 100644 js/src/tests/non262/regress/regress-554955-1.js create mode 100644 js/src/tests/non262/regress/regress-554955-2.js create mode 100644 js/src/tests/non262/regress/regress-554955-3.js create mode 100644 js/src/tests/non262/regress/regress-554955-4.js create mode 100644 js/src/tests/non262/regress/regress-554955-5.js create mode 100644 js/src/tests/non262/regress/regress-554955-6.js create mode 100644 js/src/tests/non262/regress/regress-555246-0.js create mode 100644 js/src/tests/non262/regress/regress-555246-1.js create mode 100644 js/src/tests/non262/regress/regress-559402-1.js create mode 100644 js/src/tests/non262/regress/regress-559402-2.js create mode 100644 js/src/tests/non262/regress/regress-559438.js create mode 100644 js/src/tests/non262/regress/regress-560998-1.js create mode 100644 js/src/tests/non262/regress/regress-560998-2.js create mode 100644 js/src/tests/non262/regress/regress-561031.js create mode 100644 js/src/tests/non262/regress/regress-563210.js create mode 100644 js/src/tests/non262/regress/regress-563221.js create mode 100644 js/src/tests/non262/regress/regress-566549.js create mode 100644 js/src/tests/non262/regress/regress-567152.js create mode 100644 js/src/tests/non262/regress/regress-569306.js create mode 100644 js/src/tests/non262/regress/regress-57043.js create mode 100644 js/src/tests/non262/regress/regress-571014.js create mode 100644 js/src/tests/non262/regress/regress-573875.js create mode 100644 js/src/tests/non262/regress/regress-577648-1.js create mode 100644 js/src/tests/non262/regress/regress-577648-2.js create mode 100644 js/src/tests/non262/regress/regress-580544.js create mode 100644 js/src/tests/non262/regress/regress-58116.js create mode 100644 js/src/tests/non262/regress/regress-583429.js create mode 100644 js/src/tests/non262/regress/regress-584355.js create mode 100644 js/src/tests/non262/regress/regress-585257.js create mode 100644 js/src/tests/non262/regress/regress-586482-1.js create mode 100644 js/src/tests/non262/regress/regress-586482-2.js create mode 100644 js/src/tests/non262/regress/regress-586482-3.js create mode 100644 js/src/tests/non262/regress/regress-586482-4.js create mode 100644 js/src/tests/non262/regress/regress-586482-5.js create mode 100644 js/src/tests/non262/regress/regress-588339.js create mode 100644 js/src/tests/non262/regress/regress-591846.js create mode 100644 js/src/tests/non262/regress/regress-591897.js create mode 100644 js/src/tests/non262/regress/regress-592202-3.js create mode 100644 js/src/tests/non262/regress/regress-592202-4.js create mode 100644 js/src/tests/non262/regress/regress-592556-c35.js create mode 100644 js/src/tests/non262/regress/regress-593256.js create mode 100644 js/src/tests/non262/regress/regress-595230-2.js create mode 100644 js/src/tests/non262/regress/regress-595365-1.js create mode 100644 js/src/tests/non262/regress/regress-596103.js create mode 100644 js/src/tests/non262/regress/regress-596805-1.js create mode 100644 js/src/tests/non262/regress/regress-596805-2.js create mode 100644 js/src/tests/non262/regress/regress-597945-1.js create mode 100644 js/src/tests/non262/regress/regress-597945-2.js create mode 100644 js/src/tests/non262/regress/regress-598176.js create mode 100644 js/src/tests/non262/regress/regress-600067.js create mode 100644 js/src/tests/non262/regress/regress-601399.js create mode 100644 js/src/tests/non262/regress/regress-602621.js create mode 100644 js/src/tests/non262/regress/regress-607799.js create mode 100644 js/src/tests/non262/regress/regress-607863.js create mode 100644 js/src/tests/non262/regress/regress-609617.js create mode 100644 js/src/tests/non262/regress/regress-610026.js create mode 100644 js/src/tests/non262/regress/regress-614714.js create mode 100644 js/src/tests/non262/regress/regress-617405-1.js create mode 100644 js/src/tests/non262/regress/regress-617405-2.js create mode 100644 js/src/tests/non262/regress/regress-618572.js create mode 100644 js/src/tests/non262/regress/regress-619003-1.js create mode 100644 js/src/tests/non262/regress/regress-619003-2.js create mode 100644 js/src/tests/non262/regress/regress-620376-1.js create mode 100644 js/src/tests/non262/regress/regress-624547.js create mode 100644 js/src/tests/non262/regress/regress-624968.js create mode 100644 js/src/tests/non262/regress/regress-626436.js create mode 100644 js/src/tests/non262/regress/regress-633741.js create mode 100644 js/src/tests/non262/regress/regress-634210-1.js create mode 100644 js/src/tests/non262/regress/regress-634210-2.js create mode 100644 js/src/tests/non262/regress/regress-634210-3.js create mode 100644 js/src/tests/non262/regress/regress-634210-4.js create mode 100644 js/src/tests/non262/regress/regress-636364.js create mode 100644 js/src/tests/non262/regress/regress-640075.js create mode 100644 js/src/tests/non262/regress/regress-642247.js create mode 100644 js/src/tests/non262/regress/regress-643222.js create mode 100644 js/src/tests/non262/regress/regress-646820-1.js create mode 100644 js/src/tests/non262/regress/regress-646820-2.js create mode 100644 js/src/tests/non262/regress/regress-646820-3.js create mode 100644 js/src/tests/non262/regress/regress-665355.js create mode 100644 js/src/tests/non262/regress/regress-672892.js create mode 100644 js/src/tests/non262/regress/regress-672893.js create mode 100644 js/src/tests/non262/regress/regress-68498-001.js create mode 100644 js/src/tests/non262/regress/regress-68498-002.js create mode 100644 js/src/tests/non262/regress/regress-68498-003.js create mode 100644 js/src/tests/non262/regress/regress-68498-004.js create mode 100644 js/src/tests/non262/regress/regress-694306.js create mode 100644 js/src/tests/non262/regress/regress-69607.js create mode 100644 js/src/tests/non262/regress/regress-698028-1.js create mode 100644 js/src/tests/non262/regress/regress-698028-2.js create mode 100644 js/src/tests/non262/regress/regress-698028-3.js create mode 100644 js/src/tests/non262/regress/regress-699682.js create mode 100644 js/src/tests/non262/regress/regress-71107.js create mode 100644 js/src/tests/non262/regress/regress-76054.js create mode 100644 js/src/tests/non262/regress/regress-80981.js create mode 100644 js/src/tests/non262/regress/regress-810525.js create mode 100644 js/src/tests/non262/regress/regress-82306.js create mode 100644 js/src/tests/non262/regress/regress-89443.js create mode 100644 js/src/tests/non262/regress/regress-89474.js create mode 100644 js/src/tests/non262/regress/regress-90445.js create mode 100644 js/src/tests/non262/regress/regress-96128-n.js create mode 100644 js/src/tests/non262/regress/regress-96526-001.js create mode 100644 js/src/tests/non262/regress/regress-96526-002.js create mode 100644 js/src/tests/non262/regress/regress-96526-003.js create mode 100644 js/src/tests/non262/regress/regress-98901.js create mode 100644 js/src/tests/non262/regress/shell.js create mode 100644 js/src/tests/non262/shell.js create mode 100644 js/src/tests/non262/statements/arrow-function-at-end-of-for-statement-head.js create mode 100644 js/src/tests/non262/statements/arrow-function-in-for-statement-head.js create mode 100644 js/src/tests/non262/statements/browser.js create mode 100644 js/src/tests/non262/statements/for-in-with-assignment-semantics.js create mode 100644 js/src/tests/non262/statements/for-in-with-assignment-syntax.js create mode 100644 js/src/tests/non262/statements/for-in-with-assignments.js create mode 100644 js/src/tests/non262/statements/for-in-with-declaration.js create mode 100644 js/src/tests/non262/statements/for-in-with-destructuring-assignments.js create mode 100644 js/src/tests/non262/statements/for-in-with-gc-and-unvisited-deletion.js create mode 100644 js/src/tests/non262/statements/for-in-with-gc-during-iterator-init.js create mode 100644 js/src/tests/non262/statements/for-inof-coverinitname-destr-assign.js create mode 100644 js/src/tests/non262/statements/for-inof-finally.js create mode 100644 js/src/tests/non262/statements/for-inof-loop-const-declaration.js create mode 100644 js/src/tests/non262/statements/for-inof-name-iteration-expression-contains-index-string.js create mode 100644 js/src/tests/non262/statements/for-loop-declaration-contains-computed-name.js create mode 100644 js/src/tests/non262/statements/for-loop-declaration-contains-initializer.js create mode 100644 js/src/tests/non262/statements/for-of-async-of-starting-lhs.js create mode 100644 js/src/tests/non262/statements/for-of-iterator-close-throw.js create mode 100644 js/src/tests/non262/statements/for-of-iterator-close.js create mode 100644 js/src/tests/non262/statements/for-of-iterator-primitive.js create mode 100644 js/src/tests/non262/statements/for-of-var-with-initializer.js create mode 100644 js/src/tests/non262/statements/if-constant-folding.js create mode 100644 js/src/tests/non262/statements/property-reference-self-assignment.js create mode 100644 js/src/tests/non262/statements/regress-131348.js create mode 100644 js/src/tests/non262/statements/regress-157509.js create mode 100644 js/src/tests/non262/statements/regress-194364.js create mode 100644 js/src/tests/non262/statements/regress-226517.js create mode 100644 js/src/tests/non262/statements/regress-302439.js create mode 100644 js/src/tests/non262/statements/regress-324650.js create mode 100644 js/src/tests/non262/statements/regress-444979.js create mode 100644 js/src/tests/non262/statements/regress-642975.js create mode 100644 js/src/tests/non262/statements/regress-74474-001.js create mode 100644 js/src/tests/non262/statements/regress-74474-002.js create mode 100644 js/src/tests/non262/statements/regress-74474-003.js create mode 100644 js/src/tests/non262/statements/regress-83532-001.js create mode 100644 js/src/tests/non262/statements/regress-83532-002.js create mode 100644 js/src/tests/non262/statements/shell.js create mode 100644 js/src/tests/non262/statements/trailing_comma_parameters.js create mode 100644 js/src/tests/non262/statements/try-completion.js create mode 100644 js/src/tests/non262/strict/10.4.2.js create mode 100644 js/src/tests/non262/strict/10.4.3.js create mode 100644 js/src/tests/non262/strict/10.6.js create mode 100644 js/src/tests/non262/strict/11.1.5.js create mode 100644 js/src/tests/non262/strict/11.13.1.js create mode 100644 js/src/tests/non262/strict/11.13.2.js create mode 100644 js/src/tests/non262/strict/11.3.1.js create mode 100644 js/src/tests/non262/strict/11.3.2.js create mode 100644 js/src/tests/non262/strict/11.4.1.js create mode 100644 js/src/tests/non262/strict/11.4.4.js create mode 100644 js/src/tests/non262/strict/11.4.5.js create mode 100644 js/src/tests/non262/strict/12.10.1.js create mode 100644 js/src/tests/non262/strict/12.14.1.js create mode 100644 js/src/tests/non262/strict/12.2.1-01.js create mode 100644 js/src/tests/non262/strict/12.2.1.js create mode 100644 js/src/tests/non262/strict/13.1.js create mode 100644 js/src/tests/non262/strict/15.10.7.js create mode 100644 js/src/tests/non262/strict/15.3.4.5.js create mode 100644 js/src/tests/non262/strict/15.3.5.1.js create mode 100644 js/src/tests/non262/strict/15.3.5.2.js create mode 100644 js/src/tests/non262/strict/15.4.4.11.js create mode 100644 js/src/tests/non262/strict/15.4.4.12.js create mode 100644 js/src/tests/non262/strict/15.4.4.13.js create mode 100644 js/src/tests/non262/strict/15.4.4.6.js create mode 100644 js/src/tests/non262/strict/15.4.4.8.js create mode 100644 js/src/tests/non262/strict/15.4.4.9.js create mode 100644 js/src/tests/non262/strict/15.4.5.1.js create mode 100644 js/src/tests/non262/strict/15.5.5.1.js create mode 100644 js/src/tests/non262/strict/15.5.5.2.js create mode 100644 js/src/tests/non262/strict/8.12.5.js create mode 100644 js/src/tests/non262/strict/8.12.7-2.js create mode 100644 js/src/tests/non262/strict/8.12.7.js create mode 100644 js/src/tests/non262/strict/8.7.2-01.js create mode 100644 js/src/tests/non262/strict/8.7.2.js create mode 100644 js/src/tests/non262/strict/B.1.1.js create mode 100644 js/src/tests/non262/strict/B.1.2.js create mode 100644 js/src/tests/non262/strict/assign-to-callee-name.js create mode 100644 js/src/tests/non262/strict/browser.js create mode 100644 js/src/tests/non262/strict/deprecated-octal-noctal-tokens.js create mode 100644 js/src/tests/non262/strict/directive-prologue-01.js create mode 100644 js/src/tests/non262/strict/eval-variable-environment.js create mode 100644 js/src/tests/non262/strict/primitive-assignment.js create mode 100644 js/src/tests/non262/strict/primitive-this-getter.js create mode 100644 js/src/tests/non262/strict/primitive-this-no-writeback.js create mode 100644 js/src/tests/non262/strict/rebind-eval-should-fail-in-strict-mode.js create mode 100644 js/src/tests/non262/strict/regress-532041.js create mode 100644 js/src/tests/non262/strict/regress-532254.js create mode 100644 js/src/tests/non262/strict/regress-599159.js create mode 100644 js/src/tests/non262/strict/shell.js create mode 100644 js/src/tests/non262/strict/strict-function-statements.js create mode 100644 js/src/tests/non262/strict/strict-this-is-not-truthy.js create mode 100644 js/src/tests/non262/strict/this-for-function-expression-recursion.js create mode 100644 js/src/tests/non262/strict/unbrand-this.js create mode 100644 js/src/tests/non262/syntax/browser.js create mode 100644 js/src/tests/non262/syntax/bug1863308.js create mode 100644 js/src/tests/non262/syntax/column-numbers-in-long-lines.js create mode 100644 js/src/tests/non262/syntax/declaration-forbidden-in-label.js create mode 100644 js/src/tests/non262/syntax/escaped-let-static-identifier.js create mode 100644 js/src/tests/non262/syntax/escaped-strict-reserved-words-and-yield.js create mode 100644 js/src/tests/non262/syntax/identifier_vertical_tilde.js create mode 100644 js/src/tests/non262/syntax/identifiers-with-extended-unicode-escape.js create mode 100644 js/src/tests/non262/syntax/keyword-unescaped-requirement.js create mode 100644 js/src/tests/non262/syntax/let-as-label.js create mode 100644 js/src/tests/non262/syntax/line-number-maintenance-for-identifier-containing-escape-terminated-by-unicode-separator.js create mode 100644 js/src/tests/non262/syntax/linefeed-at-eof-in-unterminated-string-or-template.js create mode 100644 js/src/tests/non262/syntax/non-simple-with-strict-directive.js create mode 100644 js/src/tests/non262/syntax/omitted-catch-binding.js create mode 100644 js/src/tests/non262/syntax/shell.js create mode 100644 js/src/tests/non262/syntax/statement-versus-statementlistitem.js create mode 100644 js/src/tests/non262/syntax/syntax-parsed-arrow-then-bigint.js create mode 100644 js/src/tests/non262/syntax/syntax-parsed-arrow-then-directive.js create mode 100644 js/src/tests/non262/syntax/syntax-parsed-arrow-then-sourcemap-directive.js create mode 100644 js/src/tests/non262/syntax/unicode_other_id_continue.js create mode 100644 js/src/tests/non262/syntax/unicode_other_id_start.js create mode 100644 js/src/tests/non262/syntax/yield-as-identifier.js create mode 100644 js/src/tests/non262/template-strings/browser.js create mode 100644 js/src/tests/non262/template-strings/bug1559123.js create mode 100644 js/src/tests/non262/template-strings/debugLineNumber.js create mode 100644 js/src/tests/non262/template-strings/lineNumber.js create mode 100644 js/src/tests/non262/template-strings/noSubst.js create mode 100644 js/src/tests/non262/template-strings/shell.js create mode 100644 js/src/tests/non262/template-strings/tagTempl.js create mode 100644 js/src/tests/non262/template-strings/templLit.js create mode 100644 js/src/tests/non262/template.js create mode 100644 js/src/tests/non262/types/8.12.5-01.js create mode 100644 js/src/tests/non262/types/browser.js create mode 100644 js/src/tests/non262/types/shell.js (limited to 'js/src/tests/non262') diff --git a/js/src/tests/non262/Array/11.1.4.js b/js/src/tests/non262/Array/11.1.4.js new file mode 100644 index 0000000000..7f39c9305e --- /dev/null +++ b/js/src/tests/non262/Array/11.1.4.js @@ -0,0 +1,68 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 260106; +var summary = 'Elisons in Array literals should not be enumed'; +var actual = ''; +var expect = ''; +var status; +var prop; +var array; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +status = summary + ' ' + inSection(1) + ' [,1] '; +array = [,1]; +actual = ''; +expect = '1'; +for (prop in array) +{ + if (prop != 'length') + { + actual += prop; + } +} +reportCompare(expect, actual, status); + +status = summary + ' ' + inSection(2) + ' [,,1] '; +array = [,,1]; +actual = ''; +expect = '2'; +for (prop in array) +{ + if (prop != 'length') + { + actual += prop; + } +} +reportCompare(expect, actual, status); + +status = summary + ' ' + inSection(3) + ' [1,] '; +array = [1,]; +actual = ''; +expect = '0'; +for (prop in array) +{ + if (prop != 'length') + { + actual += prop; + } +} +reportCompare(expect, actual, status); + +status = summary + ' ' + inSection(4) + ' [1,,] '; +array = [1,,]; +actual = ''; +expect = '0'; +for (prop in array) +{ + if (prop != 'length') + { + actual += prop; + } +} +reportCompare(expect, actual, status); diff --git a/js/src/tests/non262/Array/15.4.4.5-1.js b/js/src/tests/non262/Array/15.4.4.5-1.js new file mode 100644 index 0000000000..a5f9c9883c --- /dev/null +++ b/js/src/tests/non262/Array/15.4.4.5-1.js @@ -0,0 +1,187 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + File Name: 15.4.4.5.js + ECMA Section: Array.prototype.sort(comparefn) + Description: + + This test file tests cases in which the compare function is not supplied. + + The elements of this array are sorted. The sort is not necessarily stable. + If comparefn is provided, it should be a function that accepts two arguments + x and y and returns a negative value if x < y, zero if x = y, or a positive + value if x > y. + + 1. Call the [[Get]] method of this object with argument "length". + 2. Call ToUint32(Result(1)). + 1. Perform an implementation-dependent sequence of calls to the + [[Get]] , [[Put]], and [[Delete]] methods of this object and + toSortCompare (described below), where the first argument for each call + to [[Get]], [[Put]] , or [[Delete]] is a nonnegative integer less + than Result(2) and where the arguments for calls to SortCompare are + results of previous calls to the [[Get]] method. After this sequence + is complete, this object must have the following two properties. + (1) There must be some mathematical permutation of the nonnegative + integers less than Result(2), such that for every nonnegative integer + j less than Result(2), if property old[j] existed, then new[(j)] is + exactly the same value as old[j],. but if property old[j] did not exist, + then new[(j)] either does not exist or exists with value undefined. + (2) If comparefn is not supplied or is a consistent comparison + function for the elements of this array, then for all nonnegative + integers j and k, each less than Result(2), if old[j] compares less + than old[k] (see SortCompare below), then (j) < (k). Here we use the + notation old[j] to refer to the hypothetical result of calling the [ + [Get]] method of this object with argument j before this step is + executed, and the notation new[j] to refer to the hypothetical result + of calling the [[Get]] method of this object with argument j after this + step has been completely executed. A function is a consistent + comparison function for a set of values if (a) for any two of those + values (possibly the same value) considered as an ordered pair, it + always returns the same value when given that pair of values as its + two arguments, and the result of applying ToNumber to this value is + not NaN; (b) when considered as a relation, where the pair (x, y) is + considered to be in the relation if and only if applying the function + to x and y and then applying ToNumber to the result produces a + negative value, this relation is a partial order; and (c) when + considered as a different relation, where the pair (x, y) is considered + to be in the relation if and only if applying the function to x and y + and then applying ToNumber to the result produces a zero value (of either + sign), this relation is an equivalence relation. In this context, the + phrase "x compares less than y" means applying Result(2) to x and y and + then applying ToNumber to the result produces a negative value. + 3.Return this object. + + When the SortCompare operator is called with two arguments x and y, the following steps are taken: + 1.If x and y are both undefined, return +0. + 2.If x is undefined, return 1. + 3.If y is undefined, return 1. + 4.If the argument comparefn was not provided in the call to sort, go to step 7. + 5.Call comparefn with arguments x and y. + 6.Return Result(5). + 7.Call ToString(x). + 8.Call ToString(y). + 9.If Result(7) < Result(8), return 1. + 10.If Result(7) > Result(8), return 1. + 11.Return +0. + + Note that, because undefined always compared greater than any other value, undefined and nonexistent + property values always sort to the end of the result. It is implementation-dependent whether or not such + properties will exist or not at the end of the array when the sort is concluded. + + Note that the sort function is intentionally generic; it does not require that its this value be an Array object. + Therefore it can be transferred to other kinds of objects for use as a method. Whether the sort function can be + applied successfully to a host object is implementation dependent . + + Author: christine@netscape.com + Date: 12 november 1997 +*/ + + +var SECTION = "15.4.4.5-1"; +var TITLE = "Array.prototype.sort(comparefn)"; + +writeHeaderToLog( SECTION + " "+ TITLE); +var S = new Array(); +var item = 0; + +// array is empty. +S[item++] = "var A = new Array()"; + +// array contains one item +S[item++] = "var A = new Array( true )"; + +// length of array is 2 +S[item++] = "var A = new Array( true, false, new Boolean(true), new Boolean(false), 'true', 'false' )"; + +S[item++] = "var A = new Array(); A[3] = 'undefined'; A[6] = null; A[8] = 'null'; A[0] = void 0"; + +S[item] = "var A = new Array( "; + +var limit = 0x0061; +for ( var i = 0x007A; i >= limit; i-- ) { + S[item] += "\'"+ String.fromCharCode(i) +"\'" ; + if ( i > limit ) { + S[item] += ","; + } +} + +S[item] += ")"; + +item++; + +for ( var i = 0; i < S.length; i++ ) { + CheckItems( S[i] ); +} + +test(); + +function CheckItems( S ) { + eval( S ); + var E = Sort( A ); + + new TestCase( + S +"; A.sort(); A.length", + E.length, + eval( S + "; A.sort(); A.length") ); + + for ( var i = 0; i < E.length; i++ ) { + new TestCase( + "A["+i+ "].toString()", + E[i] +"", + A[i] +""); + + if ( A[i] == void 0 && typeof A[i] == "undefined" ) { + new TestCase( + "typeof A["+i+ "]", + typeof E[i], + typeof A[i] ); + } + } +} +function Object_1( value ) { + this.array = value.split(","); + this.length = this.array.length; + for ( var i = 0; i < this.length; i++ ) { + this[i] = eval(this.array[i]); + } + this.sort = Array.prototype.sort; + this.getClass = Object.prototype.toString; +} +function Sort( a ) { + for ( i = 0; i < a.length; i++ ) { + for ( j = i+1; j < a.length; j++ ) { + var lo = a[i]; + var hi = a[j]; + var c = Compare( lo, hi ); + if ( c == 1 ) { + a[i] = hi; + a[j] = lo; + } + } + } + return a; +} +function Compare( x, y ) { + if ( x == void 0 && y == void 0 && typeof x == "undefined" && typeof y == "undefined" ) { + return +0; + } + if ( x == void 0 && typeof x == "undefined" ) { + return 1; + } + if ( y == void 0 && typeof y == "undefined" ) { + return -1; + } + x = String(x); + y = String(y); + if ( x < y ) { + return -1; + } + if ( x > y ) { + return 1; + } + return 0; +} diff --git a/js/src/tests/non262/Array/15.4.4.5-2.js b/js/src/tests/non262/Array/15.4.4.5-2.js new file mode 100644 index 0000000000..5198297f5f --- /dev/null +++ b/js/src/tests/non262/Array/15.4.4.5-2.js @@ -0,0 +1,189 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + File Name: 15.4.4.5-2.js + ECMA Section: Array.prototype.sort(comparefn) + Description: + + This test file tests cases in which the compare function is supplied. + In this cases, the sort creates a reverse sort. + + The elements of this array are sorted. The sort is not necessarily stable. + If comparefn is provided, it should be a function that accepts two arguments + x and y and returns a negative value if x < y, zero if x = y, or a positive + value if x > y. + + 1. Call the [[Get]] method of this object with argument "length". + 2. Call ToUint32(Result(1)). + 1. Perform an implementation-dependent sequence of calls to the + [[Get]] , [[Put]], and [[Delete]] methods of this object and + toSortCompare (described below), where the first argument for each call + to [[Get]], [[Put]] , or [[Delete]] is a nonnegative integer less + than Result(2) and where the arguments for calls to SortCompare are + results of previous calls to the [[Get]] method. After this sequence + is complete, this object must have the following two properties. + (1) There must be some mathematical permutation of the nonnegative + integers less than Result(2), such that for every nonnegative integer + j less than Result(2), if property old[j] existed, then new[(j)] is + exactly the same value as old[j],. but if property old[j] did not exist, + then new[(j)] either does not exist or exists with value undefined. + (2) If comparefn is not supplied or is a consistent comparison + function for the elements of this array, then for all nonnegative + integers j and k, each less than Result(2), if old[j] compares less + than old[k] (see SortCompare below), then (j) < (k). Here we use the + notation old[j] to refer to the hypothetical result of calling the [ + [Get]] method of this object with argument j before this step is + executed, and the notation new[j] to refer to the hypothetical result + of calling the [[Get]] method of this object with argument j after this + step has been completely executed. A function is a consistent + comparison function for a set of values if (a) for any two of those + values (possibly the same value) considered as an ordered pair, it + always returns the same value when given that pair of values as its + two arguments, and the result of applying ToNumber to this value is + not NaN; (b) when considered as a relation, where the pair (x, y) is + considered to be in the relation if and only if applying the function + to x and y and then applying ToNumber to the result produces a + negative value, this relation is a partial order; and (c) when + considered as a different relation, where the pair (x, y) is considered + to be in the relation if and only if applying the function to x and y + and then applying ToNumber to the result produces a zero value (of either + sign), this relation is an equivalence relation. In this context, the + phrase "x compares less than y" means applying Result(2) to x and y and + then applying ToNumber to the result produces a negative value. + 3.Return this object. + + When the SortCompare operator is called with two arguments x and y, the following steps are taken: + 1.If x and y are both undefined, return +0. + 2.If x is undefined, return 1. + 3.If y is undefined, return 1. + 4.If the argument comparefn was not provided in the call to sort, go to step 7. + 5.Call comparefn with arguments x and y. + 6.Return Result(5). + 7.Call ToString(x). + 8.Call ToString(y). + 9.If Result(7) < Result(8), return 1. + 10.If Result(7) > Result(8), return 1. + 11.Return +0. + + Note that, because undefined always compared greater than any other value, undefined and nonexistent + property values always sort to the end of the result. It is implementation-dependent whether or not such + properties will exist or not at the end of the array when the sort is concluded. + + Note that the sort function is intentionally generic; it does not require that its this value be an Array object. + Therefore it can be transferred to other kinds of objects for use as a method. Whether the sort function can be + applied successfully to a host object is implementation dependent . + + Author: christine@netscape.com + Date: 12 november 1997 +*/ + + +var SECTION = "15.4.4.5-2"; +var TITLE = "Array.prototype.sort(comparefn)"; + +writeHeaderToLog( SECTION + " "+ TITLE); + + +var S = new Array(); +var item = 0; + +// array is empty. +S[item++] = "var A = new Array()"; + +// array contains one item +S[item++] = "var A = new Array( true )"; + +// length of array is 2 +S[item++] = "var A = new Array( true, false, new Boolean(true), new Boolean(false), 'true', 'false' )"; + +S[item++] = "var A = new Array(); A[3] = 'undefined'; A[6] = null; A[8] = 'null'; A[0] = void 0"; + +S[item] = "var A = new Array( "; + +var limit = 0x0061; +for ( var i = 0x007A; i >= limit; i-- ) { + S[item] += "\'"+ String.fromCharCode(i) +"\'" ; + if ( i > limit ) { + S[item] += ","; + } +} + +S[item] += ")"; + +for ( var i = 0; i < S.length; i++ ) { + CheckItems( S[i] ); +} + +test(); + +function CheckItems( S ) { + eval( S ); + var E = Sort( A ); + + new TestCase( + S +"; A.sort(Compare); A.length", + E.length, + eval( S + "; A.sort(Compare); A.length") ); + + for ( var i = 0; i < E.length; i++ ) { + new TestCase( + "A["+i+ "].toString()", + E[i] +"", + A[i] +""); + + if ( A[i] == void 0 && typeof A[i] == "undefined" ) { + new TestCase( + "typeof A["+i+ "]", + typeof E[i], + typeof A[i] ); + } + } +} +function Object_1( value ) { + this.array = value.split(","); + this.length = this.array.length; + for ( var i = 0; i < this.length; i++ ) { + this[i] = eval(this.array[i]); + } + this.sort = Array.prototype.sort; + this.getClass = Object.prototype.toString; +} +function Sort( a ) { + var r1 = a.length; + for ( i = 0; i < a.length; i++ ) { + for ( j = i+1; j < a.length; j++ ) { + var lo = a[i]; + var hi = a[j]; + var c = Compare( lo, hi ); + if ( c == 1 ) { + a[i] = hi; + a[j] = lo; + } + } + } + return a; +} +function Compare( x, y ) { + if ( x == void 0 && y == void 0 && typeof x == "undefined" && typeof y == "undefined" ) { + return +0; + } + if ( x == void 0 && typeof x == "undefined" ) { + return 1; + } + if ( y == void 0 && typeof y == "undefined" ) { + return -1; + } + x = String(x); + y = String(y); + if ( x < y ) { + return 1; + } + if ( x > y ) { + return -1; + } + return 0; +} diff --git a/js/src/tests/non262/Array/15.4.4.5-3.js b/js/src/tests/non262/Array/15.4.4.5-3.js new file mode 100644 index 0000000000..523a8a2a92 --- /dev/null +++ b/js/src/tests/non262/Array/15.4.4.5-3.js @@ -0,0 +1,145 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + File Name: 15.4.4.5-3.js + ECMA Section: Array.prototype.sort(comparefn) + Description: + + This is a regression test for + http://scopus/bugsplat/show_bug.cgi?id=117144 + + Verify that sort is successfull, even if the sort compare function returns + a very large negative or positive value. + + Author: christine@netscape.com + Date: 12 november 1997 +*/ + + +var SECTION = "15.4.4.5-3"; +var TITLE = "Array.prototype.sort(comparefn)"; + +writeHeaderToLog( SECTION + " "+ TITLE); + +var array = new Array(); + +var TIME_2000 = 946684800000; +var TIME_1900 = -2208988800000; + +array[array.length] = new Date( TIME_2000 * Math.PI ); +array[array.length] = new Date( TIME_2000 * 10 ); +array[array.length] = new Date( TIME_1900 + TIME_1900 ); +array[array.length] = new Date(0); +array[array.length] = new Date( TIME_2000 ); +array[array.length] = new Date( TIME_1900 + TIME_1900 +TIME_1900 ); +array[array.length] = new Date( TIME_1900 * Math.PI ); +array[array.length] = new Date( TIME_1900 * 10 ); +array[array.length] = new Date( TIME_1900 ); +array[array.length] = new Date( TIME_2000 + TIME_2000 ); +array[array.length] = new Date( 1899, 0, 1 ); +array[array.length] = new Date( 2000, 1, 29 ); +array[array.length] = new Date( 2000, 0, 1 ); +array[array.length] = new Date( 1999, 11, 31 ); + +var testarr1 = new Array(); +clone( array, testarr1 ); +testarr1.sort( comparefn1 ); + +var testarr2 = new Array(); +clone( array, testarr2 ); +testarr2.sort( comparefn2 ); + +testarr3 = new Array(); +clone( array, testarr3 ); +testarr3.sort( comparefn3 ); + +// when there's no sort function, sort sorts by the toString value of Date. + +var testarr4 = new Array(); +clone( array, testarr4 ); +testarr4.sort(); + +var realarr = new Array(); +clone( array, realarr ); +realarr.sort( realsort ); + +var stringarr = new Array(); +clone( array, stringarr ); +stringarr.sort( stringsort ); + +for ( var i = 0; i < array.length; i++) { + new TestCase( + "testarr1["+i+"]", + realarr[i], + testarr1[i] ); +} + +for ( var i=0; i < array.length; i++) { + new TestCase( + "testarr2["+i+"]", + realarr[i], + testarr2[i] ); +} + +for ( var i=0; i < array.length; i++) { + new TestCase( + "testarr3["+i+"]", + realarr[i], + testarr3[i] ); +} + +for ( var i=0; i < array.length; i++) { + new TestCase( + "testarr4["+i+"]", + stringarr[i].toString(), + testarr4[i].toString() ); +} + +test(); + +function comparefn1( x, y ) { + return x - y; +} +function comparefn2( x, y ) { + return x.valueOf() - y.valueOf(); +} +function realsort( x, y ) { + return ( x.valueOf() == y.valueOf() ? 0 : ( x.valueOf() > y.valueOf() ? 1 : -1 ) ); +} +function comparefn3( x, y ) { + return ( x == y ? 0 : ( x > y ? 1: -1 ) ); +} +function clone( source, target ) { + for (i = 0; i < source.length; i++ ) { + target[i] = source[i]; + } +} +function stringsort( x, y ) { + for ( var i = 0; i < x.toString().length; i++ ) { + var d = (x.toString()).charCodeAt(i) - (y.toString()).charCodeAt(i); + if ( d > 0 ) { + return 1; + } else { + if ( d < 0 ) { + return -1; + } else { + continue; + } + } + + var d = x.length - y.length; + + if ( d > 0 ) { + return 1; + } else { + if ( d < 0 ) { + return -1; + } + } + } + return 0; +} diff --git a/js/src/tests/non262/Array/array-001.js b/js/src/tests/non262/Array/array-001.js new file mode 100644 index 0000000000..4ddf15e604 --- /dev/null +++ b/js/src/tests/non262/Array/array-001.js @@ -0,0 +1,85 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Date: 24 September 2001 + * + * SUMMARY: Truncating arrays that have decimal property names. + * From correspondence with Igor Bukanov : + */ +//----------------------------------------------------------------------------- +var UBound = 0; +var BUGNUMBER = '(none)'; +var summary = 'Truncating arrays that have decimal property names'; +var BIG_INDEX = 4294967290; +var status = ''; +var statusitems = []; +var actual = ''; +var actualvalues = []; +var expect= ''; +var expectedvalues = []; + + +var arr = Array(BIG_INDEX); +arr[BIG_INDEX - 1] = 'a'; +arr[BIG_INDEX - 10000] = 'b'; +arr[BIG_INDEX - 0.5] = 'c'; // not an array index - but a valid property name +// Truncate the array - +arr.length = BIG_INDEX - 5000; + + +// Enumerate its properties with for..in +var s = ''; +for (var i in arr) +{ + s += arr[i]; +} + + +/* + * We expect s == 'cb' or 'bc' (EcmaScript does not fix the order). + * Note 'c' is included: for..in includes ALL enumerable properties, + * not just array-index properties. The bug was: Rhino gave s == ''. + */ +status = inSection(1); +actual = sortThis(s); +expect = 'bc'; +addThis(); + + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + + +function sortThis(str) +{ + var chars = str.split(''); + chars = chars.sort(); + return chars.join(''); +} + + +function addThis() +{ + statusitems[UBound] = status; + actualvalues[UBound] = actual; + expectedvalues[UBound] = expect; + UBound++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + for (var i=0; i y > x)] + ] + + // Test that calling each method in a different compartment returns an array, and that + // the returned array's prototype matches the other compartment's Array prototype, + // not this one. + for (const [name, arr] of arrays) { + assertEq(arr instanceof Array, false, name + " returned an instance of Array"); + assertEq(arr instanceof otherGlobal.Array, true, name + " did not return an instance of new global's Array"); + assertEq(Object.getPrototypeOf(arr) !== Object.getPrototypeOf([1, 2, 3]), true, + name + " returned an object with a prototype from the wrong realm"); + } +} + +test(newGlobal()); +test(newGlobal({newCompartment: true})); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Array/change-array-by-copy-errors-from-correct-realm.js b/js/src/tests/non262/Array/change-array-by-copy-errors-from-correct-realm.js new file mode 100644 index 0000000000..6aab79b27e --- /dev/null +++ b/js/src/tests/non262/Array/change-array-by-copy-errors-from-correct-realm.js @@ -0,0 +1,77 @@ +// |reftest| + +function test(otherGlobal) { + assertEq(TypeError !== otherGlobal.TypeError, true); + assertEq(Object.getPrototypeOf(TypeError) !== Object.getPrototypeOf(otherGlobal.TypeError), true); + assertEq(RangeError !== otherGlobal.RangeError, true); + assertEq(Object.getPrototypeOf(RangeError) !== Object.getPrototypeOf(otherGlobal.RangeError), true); + + + var arrayLike = { + get "0"() { + throw new Error("Get 0"); + }, + get "4294967295" () { // 2 ** 32 - 1 + throw new Error("Get 2147483648"); + }, + get "4294967296" () { // 2 ** 32 + throw new Error("Get 2147483648"); + }, + length: 2 ** 32 + }; + + let gToSorted = otherGlobal.Array.prototype.toSorted; + let gToSpliced = otherGlobal.Array.prototype.toSpliced; + let gToReversed = otherGlobal.Array.prototype.toReversed; + let gWith = otherGlobal.Array.prototype.with; + + let typeErrorCalls = [ + ["toSorted - bad comparator", () => gToSorted.call([], 5)], + ["toSorted - this is null", () => gToSorted.call(null)], + ["toSpliced - array too long", () => { + var oldLen = arrayLike.length; + arrayLike.length = 2**53 - 1; + gToSpliced.call(arrayLike, 0, 0, 1); + arrayLike.length = oldLen; + }] + ] + + let rangeErrorCalls = [ + ["toSorted - array too long", () => gToSorted.call(arrayLike)], + ["toReversed - array too long", () => gToReversed.call(arrayLike)], + ["toSpliced - adding elements would exceed max array length", () => gToSpliced.call(arrayLike, 0, 0)], + ["with - index out of range", () => gWith.call([0, 1, 2], 3, 7)], + ["with - negative index", () => gWith.call([0, 1, 2], -4, 7)], + ["with - array too long", () => gWith.call(arrayLike, 0, 0)] + ] + + // For each erroneous case, make sure the error comes from + // the other realm (not this realm) + for (const [message, f] of typeErrorCalls) { + try { + f(); + } catch (exc) { + assertEq(exc instanceof TypeError, false, message + " threw TypeError from wrong realm"); + assertEq(exc instanceof otherGlobal.TypeError, true, message + " didn't throw TypeError from other realm"); + assertEq(Object.getPrototypeOf(exc) !== Object.getPrototypeOf(TypeError), true, + message + " TypeError has wrong prototype"); + } + } + + for (const [message, f] of rangeErrorCalls) { + try { + f(); + } catch (exc) { + assertEq(exc instanceof RangeError, false, message + " threw RangeError from wrong realm"); + assertEq(exc instanceof otherGlobal.RangeError, true, message + " didn't throw RangeError from other realm"); + assertEq(Object.getPrototypeOf(exc) !== Object.getPrototypeOf(RangeError), true, + message + " TypeError has wrong prototype"); + } + } +} + +test(newGlobal()); +test(newGlobal({newCompartment: true})); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Array/concat-proxy.js b/js/src/tests/non262/Array/concat-proxy.js new file mode 100644 index 0000000000..ab733e2f10 --- /dev/null +++ b/js/src/tests/non262/Array/concat-proxy.js @@ -0,0 +1,25 @@ +var BUGNUMBER = 1287520; +var summary = 'Array.prototype.concat should check HasProperty everytime for non-dense array'; + +print(BUGNUMBER + ": " + summary); + +var a = [1, 2, 3]; +a.constructor = { + [Symbol.species]: function(...args) { + var p = new Proxy(new Array(...args), { + defineProperty(target, propertyKey, receiver) { + if (propertyKey === "0") delete a[1]; + return Reflect.defineProperty(target, propertyKey, receiver); + } + }); + return p; + } +}; + +var p = a.concat(); +assertEq(0 in p, true); +assertEq(1 in p, false); +assertEq(2 in p, true); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/concat-spreadable-basic.js b/js/src/tests/non262/Array/concat-spreadable-basic.js new file mode 100644 index 0000000000..c13f8f5cd3 --- /dev/null +++ b/js/src/tests/non262/Array/concat-spreadable-basic.js @@ -0,0 +1,37 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ +"use strict"; + +const x = Object.freeze([1, 2, 3]); + +let fakeArray = { + [Symbol.isConcatSpreadable]: true, + length: 2, + 0: "hello", + 1: "world" +} +assertDeepEq(x.concat(fakeArray), [1, 2, 3, "hello", "world"]); +assertDeepEq(x.concat(fakeArray, fakeArray), [1, 2, 3, "hello", "world", "hello", "world"]); + +for (let truthy of [true, 3.41, "abc", Symbol(), {}]) { + let obj = {[Symbol.isConcatSpreadable]: truthy, length: 1, 0: "hey"} + assertDeepEq(x.concat(obj), [1, 2, 3, "hey"]); +} + +for (let notTruthy of [null, undefined, false, 0, NaN, ""]) { + let obj = {[Symbol.isConcatSpreadable]: notTruthy, length: 1, 0: "hey"} + assertDeepEq(x.concat(obj), [1, 2, 3, obj]); +} + +let array = [5, 4]; +assertDeepEq(x.concat(array), [1, 2, 3, 5, 4]); + +// Can make arrays non-spreadable +array[Symbol.isConcatSpreadable] = false; +assertDeepEq(x.concat(array), [1, 2, 3, [5, 4]]); + +// Explicitly spreadable +array[Symbol.isConcatSpreadable] = true; +assertDeepEq(x.concat(array), [1, 2, 3, 5, 4]); + +reportCompare(true, true); diff --git a/js/src/tests/non262/Array/concat-spreadable-primitive.js b/js/src/tests/non262/Array/concat-spreadable-primitive.js new file mode 100644 index 0000000000..d2264bfa2a --- /dev/null +++ b/js/src/tests/non262/Array/concat-spreadable-primitive.js @@ -0,0 +1,34 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ +"use strict"; + +// Primitive values should never be tried to spread +let primitives = [ + 10, + false, + Symbol() + // Can't change String.prototype.length +]; + +for (let value of primitives) { + let prototype = Object.getPrototypeOf(value); + prototype[Symbol.isConcatSpreadable] = true; + + Object.defineProperty(prototype, "length", { + configurable: true, + get() { + // Should never invoke length getter + assertEq(true, false); + }, + }); + + let x = [1, 2].concat(value); + assertDeepEq(x, [1, 2, value]); + + delete prototype[Symbol.isConcatSpreadable]; + delete prototype.length; + + prototype.length; +} + +reportCompare(true, true); diff --git a/js/src/tests/non262/Array/fill.js b/js/src/tests/non262/Array/fill.js new file mode 100644 index 0000000000..70f1e0b522 --- /dev/null +++ b/js/src/tests/non262/Array/fill.js @@ -0,0 +1,97 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 911147; +var summary = 'Array.prototype.fill'; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +assertEq(typeof [].fill, 'function'); +assertEq([].fill.length, 1); + +// Default values for arguments and absolute values for negative start and end +// arguments are resolved correctly. +assertDeepEq([].fill(1), []); +assertDeepEq([1,1,1].fill(2), [2,2,2]); +assertDeepEq([1,1,1].fill(2, 1), [1,2,2]); +assertDeepEq([1,1,1].fill(2, 1, 2), [1,2,1]); +assertDeepEq([1,1,1].fill(2, -2), [1,2,2]); +assertDeepEq([1,1,1].fill(2, -2, -1), [1,2,1]); +assertDeepEq([1,1,1].fill(2, undefined), [2,2,2]); +assertDeepEq([1,1,1].fill(2, undefined, undefined), [2,2,2]); +assertDeepEq([1,1,1].fill(2, 1, undefined), [1,2,2]); +assertDeepEq([1,1,1].fill(2, undefined, 1), [2,1,1]); +assertDeepEq([1,1,1].fill(2, 2, 1), [1,1,1]); +assertDeepEq([1,1,1].fill(2, -1, 1), [1,1,1]); +assertDeepEq([1,1,1].fill(2, -2, 1), [1,1,1]); +assertDeepEq([1,1,1].fill(2, 1, -2), [1,1,1]); +assertDeepEq([1,1,1].fill(2, 0.1), [2,2,2]); +assertDeepEq([1,1,1].fill(2, 0.9), [2,2,2]); +assertDeepEq([1,1,1].fill(2, 1.1), [1,2,2]); +assertDeepEq([1,1,1].fill(2, 0.1, 0.9), [1,1,1]); +assertDeepEq([1,1,1].fill(2, 0.1, 1.9), [2,1,1]); +assertDeepEq([1,1,1].fill(2, 0.1, 1.9), [2,1,1]); +assertDeepEq([1,1,1].fill(2, -0), [2,2,2]); +assertDeepEq([1,1,1].fill(2, 0, -0), [1,1,1]); +assertDeepEq([1,1,1].fill(2, NaN), [2,2,2]); +assertDeepEq([1,1,1].fill(2, 0, NaN), [1,1,1]); +assertDeepEq([1,1,1].fill(2, false), [2,2,2]); +assertDeepEq([1,1,1].fill(2, true), [1,2,2]); +assertDeepEq([1,1,1].fill(2, "0"), [2,2,2]); +assertDeepEq([1,1,1].fill(2, "1"), [1,2,2]); +assertDeepEq([1,1,1].fill(2, "-2"), [1,2,2]); +assertDeepEq([1,1,1].fill(2, "-2", "-1"), [1,2,1]); +assertDeepEq([1,1,1].fill(2, {valueOf: ()=>1}), [1,2,2]); +assertDeepEq([1,1,1].fill(2, 0, {valueOf: ()=>1}), [2,1,1]); + +// fill works generically for objects, too. +assertDeepEq([].fill.call({length: 2}, 2), {0: 2, 1: 2, length: 2}); + +var setterCalled = false; +var objWithSetter = {set "0"(val) { setterCalled = true}, length: 1}; +[].fill.call(objWithSetter, 2); +assertEq(setterCalled, true); + +var setHandlerCallCount = 0; +var proxy = new Proxy({length: 3}, {set(t, i, v, r) { setHandlerCallCount++; return true; }}); +[].fill.call(proxy, 2); +assertEq(setHandlerCallCount, 3); + +var valueOfCallCount = 0; +var typedArray = new Uint8ClampedArray(3); +[].fill.call(typedArray, {valueOf: function() {valueOfCallCount++; return 2000;}}); +assertEq(valueOfCallCount, 3); +assertEq(typedArray[0], 0xff); + +// All remaining cases should throw. +var objWithGetterOnly = {get "0"() {return 1;}, length: 1}; + +var objWithReadOnlyProp = {length: 1}; +Object.defineProperty(objWithReadOnlyProp, 0, {value: 1, writable: false}); + +var objWithNonconfigurableProp = {length: 1}; +Object.defineProperty(objWithNonconfigurableProp, 0, {value: 1, configurable: false}); + +var frozenObj = {length: 1}; +Object.freeze(frozenObj); + +var frozenArray = [1, 1, 1]; +Object.freeze(frozenArray); + +assertThrowsInstanceOf(() => [].fill.call(objWithGetterOnly, 2), TypeError); +assertThrowsInstanceOf(() => [].fill.call(objWithReadOnlyProp, 2), TypeError); +assertThrowsInstanceOf(() => [].fill.call(objWithNonconfigurableProp, 2), TypeError); +assertThrowsInstanceOf(() => [].fill.call(frozenObj, 2), TypeError); +assertThrowsInstanceOf(() => [].fill.call(frozenArray, 2), TypeError); +assertThrowsInstanceOf(() => [].fill.call("111", 2), TypeError); +assertThrowsInstanceOf(() => [].fill.call(null, 2), TypeError); +assertThrowsInstanceOf(() => [].fill.call(undefined, 2), TypeError); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/filter.js b/js/src/tests/non262/Array/filter.js new file mode 100644 index 0000000000..6cb9290147 --- /dev/null +++ b/js/src/tests/non262/Array/filter.js @@ -0,0 +1,53 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = "364603"; +var summary = "The value placed in a filtered array for an element is the " + + " element's value before the callback is run, not after"; +var actual, expect; + +printBugNumber(BUGNUMBER); +printStatus(summary); + +/************** + * BEGIN TEST * + **************/ + +var failed = false; + +function mutate(val, index, arr) +{ + arr[index] = "mutated"; + return true; +} + +function assertEqual(v1, v2, msg) +{ + if (v1 !== v2) + throw msg; +} + +try +{ + var a = [1, 2]; + var m = a.filter(mutate); + + assertEqual(a[0], "mutated", "Array a not mutated!"); + assertEqual(a[1], "mutated", "Array a not mutated!"); + + assertEqual(m[0], 1, "Filtered value is value before callback is run"); + assertEqual(m[1], 2, "Filtered value is value before callback is run"); +} +catch (e) +{ + failed = e; +} + + +expect = false; +actual = failed; + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/Array/findLast_findLastIndex.js b/js/src/tests/non262/Array/findLast_findLastIndex.js new file mode 100644 index 0000000000..00f5640308 --- /dev/null +++ b/js/src/tests/non262/Array/findLast_findLastIndex.js @@ -0,0 +1,285 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 1704385; +var summary = 'Array.prototype.findLast and Array.prototype.findLastIndex'; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function isString(v, index, array) +{ + assertEq(array[index], v); + return typeof v == 'string'; +} + +function dumpError(e) +{ + var s = e.name + ': ' + e.message + + ' File: ' + e.fileName + + ', Line: ' + e.lineNumber + + ', Stack: ' + e.stack; + return s; +} + +var expect; +var actual; +var obj; + +var strings = ['hello', 'Array', 'WORLD']; +var mixed = [0, '1', 2]; +var sparsestrings = new Array(); +sparsestrings[2] = 'sparse'; +var arraylike = {0:0, 1:'string', 2:2, length:3}; +// array for which JSObject::isIndexed() holds. +var indexedArray = []; +Object.defineProperty(indexedArray, 42, { get: function() { return 42; } }); +Object.defineProperty(indexedArray, 142, { get: function() { return 'string'; } }); + +// findLast and findLastIndex have 1 required argument + +expect = 1; +actual = Array.prototype.findLast.length; +reportCompare(expect, actual, 'Array.prototype.findLast.length == 1'); +actual = Array.prototype.findLastIndex.length; +reportCompare(expect, actual, 'Array.prototype.findLastIndex.length == 1'); + +// throw TypeError if no predicate specified +expect = 'TypeError'; +try +{ + strings.findLast(); + actual = 'no error'; +} +catch(e) +{ + actual = e.name; +} +reportCompare(expect, actual, 'Array.findLast(undefined) throws TypeError'); +try +{ + strings.findLastIndex(); + actual = 'no error'; +} +catch(e) +{ + actual = e.name; +} +reportCompare(expect, actual, 'Array.findLastIndex(undefined) throws TypeError'); + +// Length gets treated as integer, not uint32 +obj = { length: -4294967295, 0: 42 }; +expected = undefined; +actual = Array.prototype.findLast.call(obj, () => true); +reportCompare(expected, actual, 'findLast correctly treats "length" as an integer'); +expected = -1 +actual = Array.prototype.findLastIndex.call(obj, () => true); +reportCompare(expected, actual, 'findLastIndex correctly treats "length" as an integer'); + +// test findLast and findLastIndex results +try +{ + expect = 'WORLD'; + actual = strings.findLast(isString); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, 'strings: findLast finds last string element'); + +try +{ + expect = 2; + actual = strings.findLastIndex(isString); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, 'strings: findLastIndex finds last string element'); + +try +{ + expect = '1'; + actual = mixed.findLast(isString); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, 'mixed: findLast finds last string element'); + +try +{ + expect = 1; + actual = mixed.findLastIndex(isString); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, 'mixed: findLastIndex finds last string element'); + +try +{ + expect = 'sparse'; + actual = sparsestrings.findLast(isString); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, 'sparsestrings: findLast finds last string element'); + +try +{ + expect = 2; + actual = sparsestrings.findLastIndex(isString); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, 'sparsestrings: findLastIndex finds first string element'); + +try +{ + expect = 'string'; + actual = [].findLast.call(arraylike, isString); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, 'arraylike: findLast finds last string element'); + +try +{ + expect = 1; + actual = [].findLastIndex.call(arraylike, isString); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, 'arraylike: findLastIndex finds last string element'); + +try +{ + expect = 1; + actual = 0; + Array.prototype.findLast.call({get 0(){ actual++ }, length: 1}, ()=>true); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, 'arraylike with getter: getter only called once'); + +try +{ + expect = 'string'; + actual = [].findLast.call(indexedArray, isString); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, 'indexedArray: findLast finds last string element'); + +try +{ + expect = 142; + actual = [].findLastIndex.call(indexedArray, isString); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, 'indexedArray: findLastIndex finds last string element'); + +// Bug 1058394 - Array#findLast and Array#findLastIndex no longer skip holes too. +var sparseArray = [1,,]; +var sparseArrayWithInheritedDataProperty = Object.setPrototypeOf([1,,,], { + __proto__: [].__proto__, + 2 : 0 +}); +var sparseArrayWithInheritedAccessorProperty = Object.setPrototypeOf([1,,,], { + __proto__: [].__proto__, + get 2(){ + throw "get 2"; + } +}); + +try +{ + expect = undefined; + actual = sparseArray.findLast(() => true); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, "Don't skip holes in Array#findLast."); + +try +{ + expect = 1; + actual = sparseArray.findLastIndex(() => true); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, "Don't skip holes in Array#findLastIndex."); + +try +{ + expect = 0; + actual = sparseArrayWithInheritedDataProperty.findLast(v => v === 0); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, "Array#findLast can find inherited data property."); + +try +{ + expect = 2; + actual = sparseArrayWithInheritedDataProperty.findLastIndex(v => v === 0); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, "Array#findLastIndex can find inherited data property."); + +try +{ + expect = "get 2"; + actual = sparseArrayWithInheritedAccessorProperty.findLast(() => true); +} +catch(e) +{ + actual = e; +} +reportCompare(expect, actual, "Array#findLast can find inherited accessor property."); + +try +{ + expect = "get 2"; + actual = sparseArrayWithInheritedAccessorProperty.findLastIndex(() => true); +} +catch(e) +{ + actual = e; +} +reportCompare(expect, actual, "Array#findLastIndex can find inherited accessor property."); diff --git a/js/src/tests/non262/Array/find_findindex.js b/js/src/tests/non262/Array/find_findindex.js new file mode 100644 index 0000000000..6e32ea6b05 --- /dev/null +++ b/js/src/tests/non262/Array/find_findindex.js @@ -0,0 +1,285 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 885553; +var summary = 'Array.prototype.find and Array.prototype.findIndex'; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function isString(v, index, array) +{ + assertEq(array[index], v); + return typeof v == 'string'; +} + +function dumpError(e) +{ + var s = e.name + ': ' + e.message + + ' File: ' + e.fileName + + ', Line: ' + e.lineNumber + + ', Stack: ' + e.stack; + return s; +} + +var expect; +var actual; +var obj; + +var strings = ['hello', 'Array', 'WORLD']; +var mixed = [0, '1', 2]; +var sparsestrings = new Array(); +sparsestrings[2] = 'sparse'; +var arraylike = {0:0, 1:'string', 2:2, length:3}; +// array for which JSObject::isIndexed() holds. +var indexedArray = []; +Object.defineProperty(indexedArray, 42, { get: function() { return 42; } }); +Object.defineProperty(indexedArray, 142, { get: function() { return 'string'; } }); + +// find and findIndex have 1 required argument + +expect = 1; +actual = Array.prototype.find.length; +reportCompare(expect, actual, 'Array.prototype.find.length == 1'); +actual = Array.prototype.findIndex.length; +reportCompare(expect, actual, 'Array.prototype.findIndex.length == 1'); + +// throw TypeError if no predicate specified +expect = 'TypeError'; +try +{ + strings.find(); + actual = 'no error'; +} +catch(e) +{ + actual = e.name; +} +reportCompare(expect, actual, 'Array.find(undefined) throws TypeError'); +try +{ + strings.findIndex(); + actual = 'no error'; +} +catch(e) +{ + actual = e.name; +} +reportCompare(expect, actual, 'Array.findIndex(undefined) throws TypeError'); + +// Length gets treated as integer, not uint32 +obj = { length: -4294967295, 0: 42 }; +expected = undefined; +actual = Array.prototype.find.call(obj, () => true); +reportCompare(expected, actual, 'find correctly treats "length" as an integer'); +expected = -1 +actual = Array.prototype.findIndex.call(obj, () => true); +reportCompare(expected, actual, 'findIndex correctly treats "length" as an integer'); + +// test find and findIndex results +try +{ + expect = 'hello'; + actual = strings.find(isString); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, 'strings: find finds first string element'); + +try +{ + expect = 0; + actual = strings.findIndex(isString); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, 'strings: findIndex finds first string element'); + +try +{ + expect = '1'; + actual = mixed.find(isString); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, 'mixed: find finds first string element'); + +try +{ + expect = 1; + actual = mixed.findIndex(isString); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, 'mixed: findIndex finds first string element'); + +try +{ + expect = 'sparse'; + actual = sparsestrings.find(isString); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, 'sparsestrings: find finds first string element'); + +try +{ + expect = 2; + actual = sparsestrings.findIndex(isString); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, 'sparsestrings: findIndex finds first string element'); + +try +{ + expect = 'string'; + actual = [].find.call(arraylike, isString); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, 'arraylike: find finds first string element'); + +try +{ + expect = 1; + actual = [].findIndex.call(arraylike, isString); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, 'arraylike: findIndex finds first string element'); + +try +{ + expect = 1; + actual = 0; + Array.prototype.find.call({get 0(){ actual++ }, length: 1}, ()=>true); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, 'arraylike with getter: getter only called once'); + +try +{ + expect = 'string'; + actual = [].find.call(indexedArray, isString); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, 'indexedArray: find finds first string element'); + +try +{ + expect = 142; + actual = [].findIndex.call(indexedArray, isString); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, 'indexedArray: findIndex finds first string element'); + +// Bug 1058394 - Array#find and Array#findIndex no longer skip holes +var sparseArray = [,,1]; +var sparseArrayWithInheritedDataProperty = Object.setPrototypeOf([,,1], { + __proto__: [].__proto__, + 0 : 0 +}); +var sparseArrayWithInheritedAccessorProperty = Object.setPrototypeOf([,,1], { + __proto__: [].__proto__, + get 0(){ + throw "get 0"; + } +}); + +try +{ + expect = undefined; + actual = sparseArray.find(() => true); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, "Don't skip holes in Array#find."); + +try +{ + expect = 0; + actual = sparseArray.findIndex(() => true); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, "Don't skip holes in Array#findIndex."); + +try +{ + expect = 0; + actual = sparseArrayWithInheritedDataProperty.find(v => v === 0); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, "Array#find can find inherited data property."); + +try +{ + expect = 0; + actual = sparseArrayWithInheritedDataProperty.findIndex(v => v === 0); +} +catch(e) +{ + actual = dumpError(e); +} +reportCompare(expect, actual, "Array#findIndex can find inherited data property."); + +try +{ + expect = "get 0"; + actual = sparseArrayWithInheritedAccessorProperty.find(() => true); +} +catch(e) +{ + actual = e; +} +reportCompare(expect, actual, "Array#find can find inherited accessor property."); + +try +{ + expect = "get 0"; + actual = sparseArrayWithInheritedAccessorProperty.findIndex(() => true); +} +catch(e) +{ + actual = e; +} +reportCompare(expect, actual, "Array#findIndex can find inherited accessor property."); diff --git a/js/src/tests/non262/Array/for_of_1.js b/js/src/tests/non262/Array/for_of_1.js new file mode 100644 index 0000000000..0233c1d278 --- /dev/null +++ b/js/src/tests/non262/Array/for_of_1.js @@ -0,0 +1,138 @@ +// Test corner cases of for-of iteration over Arrays. +// The current SetObject::construct method uses a ForOfIterator to extract +// values from the array, so we use that mechanism to test ForOfIterator here. + +// Test the properties and prototype of a generator object. +function TestManySmallArrays() { + function doIter(f, arr) { + return f(...new Set(arr)); + } + + function fun(a, b, c) { + var result = 0; + for (var i = 0; i < arguments.length; i++) + result += arguments[i]; + return result; + } + + + var TRUE_SUM = 0; + var N = 100; + var M = 3; + var sum = 0; + for (var i = 0; i < N; i++) { + var arr = new Array(M); + for (var j = 0; j < M; j++) { + arr[j] = j; + TRUE_SUM += j; + } + sum += doIter(fun, arr); + } + assertEq(sum, TRUE_SUM); +} +TestManySmallArrays(); + +// Test the properties and prototype of a generator object. +function TestSingleSmallArray() { + function doIter(f, arr) { + return f(...new Set(arr)); + } + + function fun(a, b, c) { + var result = 0; + for (var i = 0; i < arguments.length; i++) + result += arguments[i]; + return result; + } + + + var TRUE_SUM = 0; + var N = 100; + var M = 3; + var arr = new Array(M); + for (var j = 0; j < M; j++) { + arr[j] = j; + TRUE_SUM += j; + } + TRUE_SUM *= N; + + var sum = 0; + for (var i = 0; i < N; i++) { + sum += doIter(fun, arr); + } + assertEq(sum, TRUE_SUM); +} +TestSingleSmallArray(); + + +function TestChangeArrayPrototype() { + function doIter(f, arr) { + return f(...new Set(arr)); + } + + function fun(a, b, c) { + var result = 0; + for (var i = 0; i < arguments.length; i++) + result += arguments[i]; + return result; + } + + var Proto1 = Object.create(Array.prototype); + + var TRUE_SUM = 0; + var N = 100; + var MID = N/2; + var M = 3; + var arr = new Array(M); + var ARR_SUM = 0; + for (var j = 0; j < M; j++) { + arr[j] = j; + ARR_SUM += j; + } + + var sum = 0; + for (var i = 0; i < N; i++) { + sum += doIter(fun, arr); + if (i == MID) + arr.__proto__ = Proto1; + TRUE_SUM += ARR_SUM; + } + assertEq(sum, TRUE_SUM); +} +TestChangeArrayPrototype(); + + +function TestChangeManyArrayShape() { + function doIter(f, arr) { + return f(...new Set(arr)); + } + + function fun(a, b, c) { + var result = 0; + for (var i = 0; i < arguments.length; i++) + result += arguments[i]; + return result; + } + + var TRUE_SUM = 0; + var N = 100; + var MID = N/2; + var M = 3; + var sum = 0; + for (var i = 0; i < N; i++) { + var arr = new Array(M); + var ARR_SUM = 0; + for (var j = 0; j < M; j++) { + arr[j] = j; + ARR_SUM += j; + } + arr['v_' + i] = i; + sum += doIter(fun, arr); + TRUE_SUM += ARR_SUM; + } + assertEq(sum, TRUE_SUM); +} +TestChangeManyArrayShape(); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/for_of_2.js b/js/src/tests/non262/Array/for_of_2.js new file mode 100644 index 0000000000..1d5dd81fc6 --- /dev/null +++ b/js/src/tests/non262/Array/for_of_2.js @@ -0,0 +1,58 @@ +// Test corner cases of for-of iteration over Arrays. +// The current SetObject::construct method uses a ForOfIterator to extract +// values from the array, so we use that mechanism to test ForOfIterator here. + +// +// Check case where ArrayIterator.prototype.next changes in the middle of iteration. +// +function TestChangeArrayIteratorNext() { + function doIter(f, arr) { + return f(...new Set(arr)); + } + + function fun(a, b, c) { + var result = 0; + for (var i = 0; i < arguments.length; i++) + result += arguments[i]; + return result; + } + + var GET_COUNT = 0; + function getter() { + GET_COUNT++; + if (GET_COUNT == MID) + iterProto.next = NewNext; + return M2; + } + + var iter = ([])[Symbol.iterator](); + var iterProto = Object.getPrototypeOf(iter); + var OldNext = iterProto.next; + var NewNext = function () { + return OldNext.apply(this, arguments); + }; + + var TRUE_SUM = 0; + var N = 100; + var MID = N/2; + var M = 3; + var arr = new Array(M); + var ARR_SUM = 0; + for (var j = 0; j < M; j++) { + arr[j] = j; + ARR_SUM += j; + } + var M2 = (M/2)|0; + Object.defineProperty(arr, M2, {'get':getter}); + + var sum = 0; + for (var i = 0; i < N; i++) { + sum += doIter(fun, arr); + TRUE_SUM += ARR_SUM; + } + assertEq(sum, TRUE_SUM); +} +TestChangeArrayIteratorNext(); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/for_of_3.js b/js/src/tests/non262/Array/for_of_3.js new file mode 100644 index 0000000000..c90eb1f000 --- /dev/null +++ b/js/src/tests/non262/Array/for_of_3.js @@ -0,0 +1,60 @@ +// Test corner cases of for-of iteration over Arrays. +// The current SetObject::construct method uses a ForOfIterator to extract +// values from the array, so we use that mechanism to test ForOfIterator here. + +// +// Check array length increases changes during iteration. +// +function TestIncreaseArrayLength() { + function doIter(f, arr) { + return f(...new Set(arr)); + } + + function fun(a, b, c) { + var result = 0; + for (var i = 0; i < arguments.length; i++) + result += arguments[i]; + return result; + } + + var GET_COUNT = 0; + function getter() { + GET_COUNT++; + if (GET_COUNT == MID) { + ARR_SUM += arr.length; + arr.push(arr.length); + } + return M2; + } + + var iter = ([])[Symbol.iterator](); + var iterProto = Object.getPrototypeOf(iter); + var OldNext = iterProto.next; + var NewNext = function () { + return OldNext.apply(this, arguments); + }; + + var TRUE_SUM = 0; + var N = 100; + var MID = N/2; + var M = 3; + var arr = new Array(M); + var ARR_SUM = 0; + for (var j = 0; j < M; j++) { + arr[j] = j; + ARR_SUM += j; + } + var M2 = (M/2)|0; + Object.defineProperty(arr, M2, {'get':getter}); + + var sum = 0; + for (var i = 0; i < N; i++) { + sum += doIter(fun, arr); + TRUE_SUM += ARR_SUM; + } + assertEq(sum, TRUE_SUM); +} +TestIncreaseArrayLength(); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/for_of_4.js b/js/src/tests/non262/Array/for_of_4.js new file mode 100644 index 0000000000..4572727a1f --- /dev/null +++ b/js/src/tests/non262/Array/for_of_4.js @@ -0,0 +1,64 @@ +// Test corner cases of for-of iteration over Arrays. +// The current SetObject::construct method uses a ForOfIterator to extract +// values from the array, so we use that mechanism to test ForOfIterator here. + +// +// Check array length decreases changes during iteration. +// +function TestDecreaseArrayLength() { + function doIter(f, arr) { + return f(...new Set(arr)); + } + + function fun(a, b, c) { + var result = 0; + for (var i = 0; i < arguments.length; i++) + result += arguments[i]; + return result; + } + + var GET_COUNT = 0; + function getter() { + GET_COUNT++; + if (GET_COUNT == MID) { + arr.length = 0; + } + return M2; + } + + var iter = ([])[Symbol.iterator](); + var iterProto = Object.getPrototypeOf(iter); + var OldNext = iterProto.next; + var NewNext = function () { + return OldNext.apply(this, arguments); + }; + + var TRUE_SUM = 0; + var N = 100; + var MID = N/2; + var M = 3; + var arr = new Array(M); + var ARR_SUM = 0; + for (var j = 0; j < M; j++) { + arr[j] = j; + ARR_SUM += j; + } + var M2 = (M/2)|0; + Object.defineProperty(arr, M2, {'get':getter}); + + var sum = 0; + for (var i = 0; i < N; i++) { + var oldLen = arr.length; + sum += doIter(fun, arr); + var newLen = arr.length; + if (oldLen == newLen) + TRUE_SUM += arr.length > 0 ? ARR_SUM : 0; + else + TRUE_SUM += 1 + } + assertEq(sum, TRUE_SUM); +} +TestDecreaseArrayLength(); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/from-iterator-close.js b/js/src/tests/non262/Array/from-iterator-close.js new file mode 100644 index 0000000000..553c44e467 --- /dev/null +++ b/js/src/tests/non262/Array/from-iterator-close.js @@ -0,0 +1,183 @@ +var BUGNUMBER = 1180306; +var summary = 'Array.from should close iterator on error'; + +print(BUGNUMBER + ": " + summary); + +function test(ctor, { mapVal=undefined, + nextVal=undefined, + nextThrowVal=undefined, + modifier=undefined, + exceptionVal=undefined, + exceptionType=undefined, + closed=true }) { + let iterable = { + closed: false, + [Symbol.iterator]() { + let iterator = { + first: true, + next() { + if (this.first) { + this.first = false; + if (nextThrowVal) + throw nextThrowVal; + return nextVal; + } + return { value: undefined, done: true }; + }, + return() { + iterable.closed = true; + return {}; + } + }; + if (modifier) + modifier(iterator, iterable); + + return iterator; + } + }; + if (exceptionVal) { + let caught = false; + try { + ctor.from(iterable, mapVal); + } catch (e) { + assertEq(e, exceptionVal); + caught = true; + } + assertEq(caught, true); + } else if (exceptionType) { + assertThrowsInstanceOf(() => ctor.from(iterable, mapVal), exceptionType); + } else { + ctor.from(iterable, mapVal); + } + assertEq(iterable.closed, closed); +} + +// == Error cases with close == + +// ES 2017 draft 22.1.2.1 step 5.e.i.1. +// Cannot test. + +// ES 2017 draft 22.1.2.1 step 5.e.vi.2. +test(Array, { + mapVal: () => { throw "map throws"; }, + nextVal: { value: 1, done: false }, + exceptionVal: "map throws", + closed: true, +}); + +// ES 2017 draft 22.1.2.1 step 5.e.ix. +class MyArray extends Array { + constructor() { + return new Proxy({}, { + defineProperty() { + throw "defineProperty throws"; + } + }); + } +} +test(MyArray, { + nextVal: { value: 1, done: false }, + exceptionVal: "defineProperty throws", + closed: true, +}); + +// ES 2021 draft 7.4.6 step 5. +// if GetMethod fails, the thrown value should be ignored. +test(MyArray, { + nextVal: { value: 1, done: false }, + modifier: (iterator, iterable) => { + Object.defineProperty(iterator, "return", { + get: function() { + iterable.closed = true; + throw "return getter throws"; + } + }); + }, + exceptionVal: "defineProperty throws", + closed: true, +}); +test(MyArray, { + nextVal: { value: 1, done: false }, + modifier: (iterator, iterable) => { + Object.defineProperty(iterator, "return", { + get: function() { + iterable.closed = true; + return "non object"; + } + }); + }, + exceptionVal: "defineProperty throws", + closed: true, +}); +test(MyArray, { + nextVal: { value: 1, done: false }, + modifier: (iterator, iterable) => { + Object.defineProperty(iterator, "return", { + get: function() { + iterable.closed = true; + // Non callable. + return {}; + } + }); + }, + exceptionVal: "defineProperty throws", + closed: true, +}); + +// ES 2017 draft 7.4.6 steps 6. +// if return method throws, the thrown value should be ignored. +test(MyArray, { + nextVal: { value: 1, done: false }, + modifier: (iterator, iterable) => { + iterator.return = function() { + iterable.closed = true; + throw "return throws"; + }; + }, + exceptionVal: "defineProperty throws", + closed: true, +}); + +test(MyArray, { + nextVal: { value: 1, done: false }, + modifier: (iterator, iterable) => { + iterator.return = function() { + iterable.closed = true; + return "non object"; + }; + }, + exceptionVal: "defineProperty throws", + closed: true, +}); + +// == Error cases without close == + +// ES 2017 draft 22.1.2.1 step 5.e.iii. +test(Array, { + nextThrowVal: "next throws", + exceptionVal: "next throws", + closed: false, +}); + +test(Array, { + nextVal: { value: {}, get done() { throw "done getter throws"; } }, + exceptionVal: "done getter throws", + closed: false, +}); + +// ES 2017 draft 22.1.2.1 step 5.e.v. +test(Array, { + nextVal: { get value() { throw "value getter throws"; }, done: false }, + exceptionVal: "value getter throws", + closed: false, +}); + +// == Successful cases == + +test(Array, { + nextVal: { value: 1, done: false }, + closed: false, +}); + +if (typeof reportCompare === 'function') + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/from_async.js b/js/src/tests/non262/Array/from_async.js new file mode 100644 index 0000000000..d39f191f7b --- /dev/null +++ b/js/src/tests/non262/Array/from_async.js @@ -0,0 +1,302 @@ +// |reftest| skip-if(!xulRuntime.shell) -- needs drainJobQueue + +// Basic Smoke Test +async function* asyncGen(n) { + for (let i = 0; i < n; i++) { + yield i * 2; + } +} + +let done = false; +Array.fromAsync(asyncGen(4)).then((x) => { + assertEq(Array.isArray(x), true); + assertEq(x.length, 4); + assertEq(x[0], 0); + assertEq(x[1], 2); + assertEq(x[2], 4); + assertEq(x[3], 6); + done = true; +} +); + +drainJobQueue(); +assertEq(done, true); + +(async function () { + class InterruptableAsyncIterator { + count = 0 + closed = false + throwAfter = NaN + constructor(n, throwAfter = NaN) { + this.count = n; + this.throwAfter = throwAfter; + } + [Symbol.asyncIterator] = function () { + return { + iter: this, + i: 0, + async next() { + if (this.i > this.iter.throwAfter) { + throw "Exception" + } + if (this.i++ < this.iter.count) { + return Promise.resolve({ done: false, value: this.i - 1 }); + } + return Promise.resolve({ done: true, value: undefined }); + }, + async return(x) { + this.iter.closed = true; + return { value: x, done: true }; + } + } + } + } + + var one = await Array.fromAsync(new InterruptableAsyncIterator(2)); + assertEq(one.length, 2) + assertEq(one[0], 0); + assertEq(one[1], 1); + + var two = new InterruptableAsyncIterator(10, 2); + var threw = false; + try { + var res = await Array.fromAsync(two); + } catch (e) { + threw = true; + assertEq(e, "Exception"); + } + assertEq(threw, true); + // The iterator is not closed unless we have an abrupt completion while mapping. + assertEq(two.closed, false); + + // Test throwing while mapping: Iterator should be closed. + var three = new InterruptableAsyncIterator(10, 9); + threw = false; + try { + var res = await Array.fromAsync(three, (x) => { + if (x > 3) { + throw "Range" + } + return x; + }); + } catch (e) { + assertEq(e, "Range"); + threw = true; + } + assertEq(threw, true); + assertEq(three.closed, true); + + var sync = await Array.fromAsync([1, 2, 3]); + assertEq(sync.length, 3); + assertEq(sync[0], 1) + assertEq(sync[1], 2) + assertEq(sync[2], 3) + + let closed_frozen = false; + class Frozen { + constructor(x) { + this.count = x; + Object.freeze(this); + } + [Symbol.asyncIterator] = function () { + return { + iter: this, + i: 0, + async next() { + if (this.i++ < this.iter.count) { + return Promise.resolve({ done: false, value: this.i - 1 }); + } + return Promise.resolve({ done: true, value: undefined }); + }, + async return(x) { + // Can't use Frozen instance, becuse frozen is frozen. + closed_frozen = true; + return { value: x, done: true }; + } + } + } + } + + // We should close the iterator when define property throws. + // Test by defining into a frozen object. + var frozen = new Frozen(10); + threw = false; + try { + var result = await Array.fromAsync.call(Frozen, frozen); + } catch (e) { + threw = true; + } + + assertEq(threw, true); + assertEq(closed_frozen, true); + +})(); + +drainJobQueue(); + +(async function () { + var badSyncIterator = { + [Symbol.iterator]() { + return null; + } + }; + + var badAsyncIterator = { + [Symbol.asyncIterator]() { + return null; + } + }; + + async function errorMessage(fn) { + try { + await fn(); + } catch (e) { + return e.message; + } + throw new Error("missing error"); + } + + // Ensure Array.from and Array.fromAsync use consistent error reporting. + var expected = await errorMessage(() => Array.from(badSyncIterator)); + var actual = await errorMessage(() => Array.fromAsync(badSyncIterator)); + assertEq(actual, expected); + + // Ensure for-of iteration and Array.fromAsync use consistent error reporting. + var expected = await errorMessage(() => { for (var _ of badSyncIterator); }); + var actual = await errorMessage(() => Array.fromAsync(badSyncIterator)); + assertEq(actual, expected); + + // Ensure await for-of iteration and Array.fromAsync use consistent error reporting. + var expected = await errorMessage(async () => { for await (var _ of badAsyncIterator); }); + var actual = await errorMessage(() => Array.fromAsync(badAsyncIterator)); + assertEq(actual, expected); +})(); + +drainJobQueue(); + +(async function () { + function* gen() { + for (let i = 0; i < 4; ++i) { + yield Promise.resolve(i); + } + }; + + var array = await Array.fromAsync(gen()); + + // Promise values are unwrapped via AsyncFromSyncIterator. + assertEqArray(array, [0, 1, 2, 3]); +})(); + +drainJobQueue(); + +(async function () { + var badSyncIterator = { + [Symbol.iterator]: 123, + }; + + var badAsyncIterator = { + [Symbol.asyncIterator]: 123, + }; + + async function errorMessage(fn) { + try { + await fn(); + } catch (e) { + return e.message; + } + throw new Error("missing error"); + } + + // Ensure Array.from and Array.fromAsync use consistent error reporting. + var expected = await errorMessage(() => Array.from(badSyncIterator)); + var actual = await errorMessage(() => Array.fromAsync(badSyncIterator)); + assertEq(actual.endsWith("is not iterable"), expected.endsWith("is not iterable")); + + // Ensure for-of iteration and Array.fromAsync use consistent error reporting. + var expected = await errorMessage(() => { for (var _ of badSyncIterator); }); + var actual = await errorMessage(() => Array.fromAsync(badSyncIterator)); + assertEq(actual.endsWith("is not iterable"), expected.endsWith("is not iterable")); + + // Ensure await for-of iteration and Array.fromAsync use consistent error reporting. + var expected = await errorMessage(async () => { for await (var _ of badAsyncIterator); }); + var actual = await errorMessage(() => Array.fromAsync(badAsyncIterator)); + assertEq(actual.endsWith("is not iterable"), expected.endsWith("is not iterable")); +})(); + +drainJobQueue(); + + +var g = newGlobal(); +g.asyncGen = asyncGen; +var p = g.evaluate(` +Array.fromAsync(asyncGen(4)) +`) + +p.then((x) => { + assertEq(x instanceof Array, false); // Should use the other global's Array. + assertEq(x instanceof g.Array, true); +}) + +drainJobQueue(); + + +var g2 = newGlobal({ newCompartment: true }); +g2.asyncGen = asyncGen; +var p = g2.evaluate(` +Array.fromAsync(asyncGen(4)) +`) + +p.then((x) => { + assertEq(x instanceof Array, false); // Should use the other global's Array. + assertEq(x instanceof g2.Array, true); + nukeCCW(x); // this will throw if x happens to not be a CCW (it should be!) +}) +drainJobQueue(); + +// Test having a CCW 'this' value. +g2.obj = {}; +var p2 = g2.evaluate(` +Array.fromAsync.call(obj, asyncGen(4)) +`) + +p2.then((x) => { + assertEq(x instanceof Array, false); // Should use the other global's Array. + assertEq(x instanceof g2.Array, true); + nukeCCW(x); +}) + +drainJobQueue(); + +// Verify user promise resolution behaviour. +var myThenCalled = false; +var obj = { then: () => { myThenCalled = true; } } +function* genO() { + yield obj; + return; +} + +var res = Array.fromAsync(genO()); +res.then((x) => { + assertEq(x[0], obj); + assertEq(myThenCalled, true); +}); + +drainJobQueue(); + +function* thrower() { + throw new Error(); +} + +g2.thrower = thrower; +var p = g2.evaluate(`Array.fromAsync(thrower())`) +p.catch((e) => { + assertEq(e instanceof Error, true, "Should throw an error from the current global"); +}) +drainJobQueue(); + +p = g2.evaluate(`Array.fromAsync(thrower, 1)`); +p.catch((e) => assertEq(e instanceof g2.Error, true, "Should throw error from g2")) +drainJobQueue(); + +if (typeof reportCompare === 'function') + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/from_basics.js b/js/src/tests/non262/Array/from_basics.js new file mode 100644 index 0000000000..623207a41a --- /dev/null +++ b/js/src/tests/non262/Array/from_basics.js @@ -0,0 +1,51 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Array.from copies arrays. +var src = [1, 2, 3], copy = Array.from(src); +assertEq(copy === src, false); +assertEq(Array.isArray(copy), true); +assertDeepEq(copy, src); + +// Non-element properties are not copied. +var a = [0, 1]; +a.name = "lisa"; +assertDeepEq(Array.from(a), [0, 1]); + +// It's a shallow copy. +src = [[0], [1]]; +copy = Array.from(src); +assertEq(copy[0], src[0]); +assertEq(copy[1], src[1]); + +// Array.from can copy non-iterable objects, if they're array-like. +src = {0: "zero", 1: "one", length: 2}; +copy = Array.from(src); +assertEq(Array.isArray(copy), true); +assertDeepEq(copy, ["zero", "one"]); + +// Properties past the .length are not copied. +src = {0: "zero", 1: "one", 2: "two", 9: "nine", name: "lisa", length: 2}; +assertDeepEq(Array.from(src), ["zero", "one"]); + +// If an object has neither an @@iterator method nor .length, +// then it's treated as zero-length. +assertDeepEq(Array.from({}), []); + +// Source object property order doesn't matter. +src = {length: 2, 1: "last", 0: "first"}; +assertDeepEq(Array.from(src), ["first", "last"]); + +// Array.from does not preserve holes. +assertDeepEq(Array.from(Array(3)), [undefined, undefined, undefined]); +assertDeepEq(Array.from([, , 2, 3]), [undefined, undefined, 2, 3]); +assertDeepEq(Array.from([0, , , ,]), [0, undefined, undefined, undefined]); + +// Even on non-iterable objects. +assertDeepEq(Array.from({length: 4}), [undefined, undefined, undefined, undefined]); + +// Array.from should coerce negative lengths to zero. +assertDeepEq(Array.from({length: -1}), []); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Array/from_constructor.js b/js/src/tests/non262/Array/from_constructor.js new file mode 100644 index 0000000000..6846ef09aa --- /dev/null +++ b/js/src/tests/non262/Array/from_constructor.js @@ -0,0 +1,56 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Array.from can be applied to any constructor. +// For example, the Date builtin constructor. +var d = Array.from.call(Date, ["A", "B"]); +assertEq(Array.isArray(d), false); +assertEq(Object.prototype.toString.call(d), "[object Date]"); +assertEq(Object.getPrototypeOf(d), Date.prototype); +assertEq(d.length, 2); +assertEq(d[0], "A"); +assertEq(d[1], "B"); + +// Or Object. +var obj = Array.from.call(Object, []); +assertEq(Array.isArray(obj), false); +assertEq(Object.getPrototypeOf(obj), Object.prototype); +assertEq(Object.getOwnPropertyNames(obj).join(","), "length"); +assertEq(obj.length, 0); + +// Or any JS function. +function C(arg) { + this.args = arguments; +} +var c = Array.from.call(C, {length: 1, 0: "zero"}); +assertEq(c instanceof C, true); +assertEq(c.args.length, 1); +assertEq(c.args[0], 1); +assertEq(c.length, 1); +assertEq(c[0], "zero"); + +// If the 'this' value passed to Array.from is not a constructor, +// a plain Array is created. +var arr = [3, 4, 5]; +var nonconstructors = [ + {}, Math, Object.getPrototypeOf, undefined, 17, + () => ({}) // arrow functions are not constructors +]; +for (var v of nonconstructors) { + obj = Array.from.call(v, arr); + assertEq(Array.isArray(obj), true); + assertDeepEq(obj, arr); +} + +// Array.from does not get confused if global.Array is replaced with another +// constructor. +function NotArray() { +} +var RealArray = Array; +NotArray.from = Array.from; +Array = NotArray; +assertEq(RealArray.from([1]) instanceof RealArray, true); +assertEq(NotArray.from([1]) instanceof NotArray, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Array/from_errors.js b/js/src/tests/non262/Array/from_errors.js new file mode 100644 index 0000000000..cbf0eb195a --- /dev/null +++ b/js/src/tests/non262/Array/from_errors.js @@ -0,0 +1,152 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Array.from throws if the argument is undefined or null. +assertThrowsInstanceOf(() => Array.from(), TypeError); +assertThrowsInstanceOf(() => Array.from(undefined), TypeError); +assertThrowsInstanceOf(() => Array.from(null), TypeError); + +// Array.from throws if an element can't be defined on the new object. +function ObjectWithReadOnlyElement() { + Object.defineProperty(this, "0", {value: null}); + this.length = 0; +} +ObjectWithReadOnlyElement.from = Array.from; +assertDeepEq(ObjectWithReadOnlyElement.from([]), new ObjectWithReadOnlyElement); +assertThrowsInstanceOf(() => ObjectWithReadOnlyElement.from([1]), TypeError); + +// The same, but via preventExtensions. +function InextensibleObject() { + Object.preventExtensions(this); +} +InextensibleObject.from = Array.from; +assertThrowsInstanceOf(() => InextensibleObject.from([1]), TypeError); + +// We will now test this property, that Array.from throws if the .length can't +// be assigned, using several different kinds of object. +var obj; +function init(self) { + obj = self; + self[0] = self[1] = self[2] = self[3] = 0; +} + +function testUnsettableLength(C, Exc) { + if (Exc === undefined) + Exc = TypeError; // the usual expected exception type + C.from = Array.from; + + obj = null; + assertThrowsInstanceOf(() => C.from([]), Exc); + assertEq(obj instanceof C, true); + for (var i = 0; i < 4; i++) + assertEq(obj[0], 0); + + obj = null; + assertThrowsInstanceOf(() => C.from([0, 10, 20, 30]), Exc); + assertEq(obj instanceof C, true); + for (var i = 0; i < 4; i++) + assertEq(obj[i], i * 10); +} + +// Array.from throws if the new object's .length can't be assigned because +// there is no .length and the object is inextensible. +function InextensibleObject4() { + init(this); + Object.preventExtensions(this); +} +testUnsettableLength(InextensibleObject4); + +// Array.from throws if the new object's .length can't be assigned because it's +// read-only. +function ObjectWithReadOnlyLength() { + init(this); + Object.defineProperty(this, "length", {configurable: true, writable: false, value: 4}); +} +testUnsettableLength(ObjectWithReadOnlyLength); + +// The same, but using a builtin type. +Uint8Array.from = Array.from; +assertThrowsInstanceOf(() => Uint8Array.from([]), TypeError); + +// Array.from throws if the new object's .length can't be assigned because it +// inherits a readonly .length along the prototype chain. +function ObjectWithInheritedReadOnlyLength() { + init(this); +} +Object.defineProperty(ObjectWithInheritedReadOnlyLength.prototype, + "length", + {configurable: true, writable: false, value: 4}); +testUnsettableLength(ObjectWithInheritedReadOnlyLength); + +// The same, but using an object with a .length getter but no setter. +function ObjectWithGetterOnlyLength() { + init(this); + Object.defineProperty(this, "length", {configurable: true, get: () => 4}); +} +testUnsettableLength(ObjectWithGetterOnlyLength); + +// The same, but with a setter that throws. +function ObjectWithThrowingLengthSetter() { + init(this); + Object.defineProperty(this, "length", { + configurable: true, + get: () => 4, + set: () => { throw new RangeError("surprise!"); } + }); +} +testUnsettableLength(ObjectWithThrowingLengthSetter, RangeError); + +// Array.from throws if mapfn is neither callable nor undefined. +assertThrowsInstanceOf(() => Array.from([3, 4, 5], {}), TypeError); +assertThrowsInstanceOf(() => Array.from([3, 4, 5], "also not a function"), TypeError); +assertThrowsInstanceOf(() => Array.from([3, 4, 5], null), TypeError); + +// Even if the function would not have been called. +assertThrowsInstanceOf(() => Array.from([], JSON), TypeError); + +// If mapfn is not undefined and not callable, the error happens before anything else. +// Before calling the constructor, before touching the arrayLike. +var log = ""; +function C() { + log += "C"; + obj = this; +} +var p = new Proxy({}, { + has: function () { log += "1"; }, + get: function () { log += "2"; }, + getOwnPropertyDescriptor: function () { log += "3"; } +}); +assertThrowsInstanceOf(() => Array.from.call(C, p, {}), TypeError); +assertEq(log, ""); + +// If mapfn throws, the new object has already been created. +var arrayish = { + get length() { log += "l"; return 1; }, + get 0() { log += "0"; return "q"; } +}; +log = ""; +var exc = {surprise: "ponies"}; +assertThrowsValue(() => Array.from.call(C, arrayish, () => { throw exc; }), exc); +assertEq(log, "lC0"); +assertEq(obj instanceof C, true); + +// It's a TypeError if the @@iterator property is a primitive (except null and undefined). +for (var primitive of ["foo", 17, Symbol(), true]) { + assertThrowsInstanceOf(() => Array.from({[Symbol.iterator] : primitive}), TypeError); +} +assertDeepEq(Array.from({[Symbol.iterator]: null}), []); +assertDeepEq(Array.from({[Symbol.iterator]: undefined}), []); + +// It's a TypeError if the iterator's .next() method returns a primitive. +for (var primitive of [undefined, null, 17]) { + assertThrowsInstanceOf( + () => Array.from({ + [Symbol.iterator]() { + return {next() { return primitive; }}; + } + }), + TypeError); +} + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Array/from_iterable.js b/js/src/tests/non262/Array/from_iterable.js new file mode 100644 index 0000000000..5681819612 --- /dev/null +++ b/js/src/tests/non262/Array/from_iterable.js @@ -0,0 +1,50 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Array.from works on arguments objects. +(function () { + assertDeepEq(Array.from(arguments), ["arg0", "arg1", undefined]); +})("arg0", "arg1", undefined); + +// If an object has both .length and [@@iterator] properties, [@@iterator] is used. +var a = ['a', 'e', 'i', 'o', 'u']; +a[Symbol.iterator] = function* () { + for (var i = 5; i--; ) + yield this[i]; +}; + +var log = ''; +function f(x) { + log += x; + return x + x; +} + +var b = Array.from(a, f); +assertDeepEq(b, ['uu', 'oo', 'ii', 'ee', 'aa']); +assertEq(log, 'uoiea'); + +// In fact, if [@@iterator] is present, .length isn't queried at all. +var pa = new Proxy(a, { + has: function (target, id) { + if (id === "length") + throw new Error(".length should not be queried (has)"); + return id in target; + }, + get: function (target, id) { + if (id === "length") + throw new Error(".length should not be queried (get)"); + return target[id]; + }, + getOwnPropertyDescriptor: function (target, id) { + if (id === "length") + throw new Error(".length should not be queried (getOwnPropertyDescriptor)"); + return Object.getOwnPropertyDescriptor(target, id) + } +}); +log = ""; +b = Array.from(pa, f); +assertDeepEq(b, ['uu', 'oo', 'ii', 'ee', 'aa']); +assertEq(log, 'uoiea'); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Array/from_length_setter.js b/js/src/tests/non262/Array/from_length_setter.js new file mode 100644 index 0000000000..43f35f73e0 --- /dev/null +++ b/js/src/tests/non262/Array/from_length_setter.js @@ -0,0 +1,13 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Array.from calls a length setter if present. +var hits = 0; +function C() {} +C.prototype = {set length(v) { hits++; }}; +C.from = Array.from; +var copy = C.from(["A", "B"]); +assertEq(hits, 1); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Array/from_mapping.js b/js/src/tests/non262/Array/from_mapping.js new file mode 100644 index 0000000000..568b9d6d7a --- /dev/null +++ b/js/src/tests/non262/Array/from_mapping.js @@ -0,0 +1,41 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// If the mapfn argument to Array.from is undefined, don't map. +assertDeepEq(Array.from([3, 4, 5], undefined), [3, 4, 5]); +assertDeepEq(Array.from([4, 5, 6], undefined, Math), [4, 5, 6]); + +// mapfn is called with two arguments: value and index. +var log = []; +function f() { + log.push(Array.from(arguments)); + return log.length; +} +assertDeepEq(Array.from(['a', 'e', 'i', 'o', 'u'], f), [1, 2, 3, 4, 5]); +assertDeepEq(log, [['a', 0], ['e', 1], ['i', 2], ['o', 3], ['u', 4]]); + +// If the object to be copied is non-iterable, mapfn is still called with two +// arguments. +log = []; +assertDeepEq(Array.from({0: "zero", 1: "one", length: 2}, f), [1, 2]); +assertDeepEq(log, [["zero", 0], ["one", 1]]); + +// If the object to be copied is iterable and the constructor is not Array, +// mapfn is still called with two arguments. +log = []; +function C() {} +C.from = Array.from; +var c = new C; +c[0] = 1; +c[1] = 2; +c.length = 2; +assertDeepEq(C.from(["zero", "one"], f), c); +assertDeepEq(log, [["zero", 0], ["one", 1]]); + +// The mapfn is called even if the value to be mapped is undefined. +assertDeepEq(Array.from([0, 1, , 3], String), ["0", "1", "undefined", "3"]); +var arraylike = {length: 4, "0": 0, "1": 1, "3": 3}; +assertDeepEq(Array.from(arraylike, String), ["0", "1", "undefined", "3"]); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Array/from_primitive.js b/js/src/tests/non262/Array/from_primitive.js new file mode 100644 index 0000000000..e3f68d8bc2 --- /dev/null +++ b/js/src/tests/non262/Array/from_primitive.js @@ -0,0 +1,21 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +for (let primitive of [true, 3.14, "hello", Symbol()]) { + let prototype = Object.getPrototypeOf(primitive); + + Object.defineProperty(prototype, Symbol.iterator, { + configurable: true, + get() { + "use strict"; + assertEq(this, primitive); + return () => [this][Symbol.iterator](); + }, + }); + assertEq(Array.from(primitive)[0], primitive); + + delete prototype[Symbol.iterator]; +} + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Array/from_proxy.js b/js/src/tests/non262/Array/from_proxy.js new file mode 100644 index 0000000000..c3c82d0b7e --- /dev/null +++ b/js/src/tests/non262/Array/from_proxy.js @@ -0,0 +1,55 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Two tests involving Array.from and a Proxy. +var log = []; +function LoggingProxy(target) { + var h = { + defineProperty: function (t, id) { + log.push("define", id); + return true; + }, + has: function (t, id) { + log.push("has", id); + return id in t; + }, + get: function (t, id) { + log.push("get", id); + return t[id]; + }, + set: function (t, id, v) { + log.push("set", id); + t[id] = v; + return true; + } + }; + return new Proxy(target || [], h); +} + +// When the new object created by Array.from is a Proxy, +// Array.from calls handler.defineProperty to create new elements +// but handler.set to set the length. +LoggingProxy.from = Array.from; +LoggingProxy.from([3, 4, 5]); +assertDeepEq(log, ["define", "0", "define", "1", "define", "2", "set", "length"]); + +// When the argument passed to Array.from is a Proxy, Array.from +// calls handler.get on it. +log = []; +assertDeepEq(Array.from(new LoggingProxy([3, 4, 5])), [3, 4, 5]); +assertDeepEq(log, ["get", Symbol.iterator, + "get", "length", "get", "0", + "get", "length", "get", "1", + "get", "length", "get", "2", + "get", "length"]); + +// Array-like iteration only gets the length once. +log = []; +var arr = [5, 6, 7]; +arr[Symbol.iterator] = undefined; +assertDeepEq(Array.from(new LoggingProxy(arr)), [5, 6, 7]); +assertDeepEq(log, ["get", Symbol.iterator, + "get", "length", "get", "0", "get", "1", "get", "2"]); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Array/from_realms.js b/js/src/tests/non262/Array/from_realms.js new file mode 100644 index 0000000000..e3a8636063 --- /dev/null +++ b/js/src/tests/non262/Array/from_realms.js @@ -0,0 +1,37 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +if (typeof newGlobal === 'function') { + // G.Array.from, where G is any global, produces an array whose prototype + // is G.Array.prototype. + var g = newGlobal(); + var ga = g.Array.from([1, 2, 3]); + assertEq(ga instanceof g.Array, true); + + // Even if G.Array is not passed in as the 'this' value to the call. + var from = g.Array.from + var ga2 = from([1, 2, 3]); + assertEq(ga2 instanceof g.Array, true); + + // Array.from can be applied to a constructor from another realm. + var p = Array.from.call(g.Array, [1, 2, 3]); + assertEq(p instanceof g.Array, true); + var q = g.Array.from.call(Array, [3, 4, 5]); + assertEq(q instanceof Array, true); + + // The default 'this' value received by a non-strict mapping function is + // that function's global, not Array.from's global or the caller's global. + var h = newGlobal(), result = undefined; + h.mainGlobal = this; + h.eval("function f() { mainGlobal.result = this; }"); + g.Array.from.call(Array, [5, 6, 7], h.f); + // (Give each global in the test a name, for better error messages. But use + // globalName, because window.name is complicated.) + this.globalName = "main"; + g.globalName = "g"; + h.globalName = "h"; + assertEq(result.globalName, "h"); +} + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Array/from_string.js b/js/src/tests/non262/Array/from_string.js new file mode 100644 index 0000000000..3ad19e253a --- /dev/null +++ b/js/src/tests/non262/Array/from_string.js @@ -0,0 +1,23 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Array.from on a string iterates over the string. +assertDeepEq(Array.from("test string"), + ['t', 'e', 's', 't', ' ', 's', 't', 'r', 'i', 'n', 'g']); + +// Array.from on a string handles surrogate pairs correctly. +var gclef = "\uD834\uDD1E"; // U+1D11E MUSICAL SYMBOL G CLEF +assertDeepEq(Array.from(gclef), [gclef]); +assertDeepEq(Array.from(gclef + " G"), [gclef, " ", "G"]); + +// Array.from on a string calls the @@iterator method. +String.prototype[Symbol.iterator] = function* () { yield 1; yield 2; }; +assertDeepEq(Array.from("anything"), [1, 2]); + +// If the iterator method is deleted, Strings are still arraylike. +delete String.prototype[Symbol.iterator]; +assertDeepEq(Array.from("works"), ['w', 'o', 'r', 'k', 's']); +assertDeepEq(Array.from(gclef), ['\uD834', '\uDD1E']); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Array/from_surfaces.js b/js/src/tests/non262/Array/from_surfaces.js new file mode 100644 index 0000000000..680b64817c --- /dev/null +++ b/js/src/tests/non262/Array/from_surfaces.js @@ -0,0 +1,13 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Check superficial features of Array.from. +var desc = Object.getOwnPropertyDescriptor(Array, "from"); +assertEq(desc.configurable, true); +assertEq(desc.enumerable, false); +assertEq(desc.writable, true); +assertEq(Array.from.length, 1); +assertThrowsInstanceOf(() => new Array.from(), TypeError); // not a constructor + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Array/from_this.js b/js/src/tests/non262/Array/from_this.js new file mode 100644 index 0000000000..978c90b871 --- /dev/null +++ b/js/src/tests/non262/Array/from_this.js @@ -0,0 +1,48 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// The third argument to Array.from is passed as the 'this' value to the +// mapping function. +var hits = 0, obj = {}; +function f(x) { + assertEq(this, obj); + hits++; +} +Array.from(["a", "b", "c"], f, obj); +assertEq(hits, 3); + +// Without an argument, undefined is passed... +hits = 0; +function gs(x) { + "use strict"; + assertEq(this, undefined); + hits++; +} +Array.from("def", gs); +assertEq(hits, 3); + +// ...and if the mapping function is non-strict, that means the global is +// passed. +var global = this; +hits = 0; +function g(x) { + assertEq(this, global); + hits++; +} +Array.from("ghi", g); +assertEq(hits, 3); + +// A primitive value can be passed. +for (var v of [0, "str", undefined]) { + hits = 0; + var mapfn = function h(x) { + "use strict"; + assertEq(this, v); + hits++; + }; + Array.from("pq", mapfn, v); + assertEq(hits, 2); +} + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Array/frozen-dense-array.js b/js/src/tests/non262/Array/frozen-dense-array.js new file mode 100644 index 0000000000..cdb86daa3b --- /dev/null +++ b/js/src/tests/non262/Array/frozen-dense-array.js @@ -0,0 +1,42 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Author: Emilio Cobos Álvarez + */ +var BUGNUMBER = 1310744; +var summary = "Dense array properties shouldn't be modified when they're frozen"; + +print(BUGNUMBER + ": " + summary); + +var a = Object.freeze([4, 5, 1]); + +function assertArrayIsExpected() { + assertEq(a.length, 3); + assertEq(a[0], 4); + assertEq(a[1], 5); + assertEq(a[2], 1); +} + +assertThrowsInstanceOf(() => a.reverse(), TypeError); +assertThrowsInstanceOf(() => a.shift(), TypeError); +assertThrowsInstanceOf(() => a.unshift(0), TypeError); +assertThrowsInstanceOf(() => a.sort(function() {}), TypeError); +assertThrowsInstanceOf(() => a.pop(), TypeError); +assertThrowsInstanceOf(() => a.fill(0), TypeError); +assertThrowsInstanceOf(() => a.splice(0, 1, 1), TypeError); +assertThrowsInstanceOf(() => a.push("foo"), TypeError); +assertThrowsInstanceOf(() => { "use strict"; a.length = 5; }, TypeError); +assertThrowsInstanceOf(() => { "use strict"; a[2] = "foo"; }, TypeError); +assertThrowsInstanceOf(() => { "use strict"; delete a[0]; }, TypeError); +assertThrowsInstanceOf(() => a.splice(Math.a), TypeError); + +// Shouldn't throw, since this is not strict mode, but shouldn't change the +// value of the property. +a.length = 5; +a[2] = "foo"; +assertEq(delete a[0], false); + +assertArrayIsExpected(); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/frozen-dict-mode-length.js b/js/src/tests/non262/Array/frozen-dict-mode-length.js new file mode 100644 index 0000000000..e519b58920 --- /dev/null +++ b/js/src/tests/non262/Array/frozen-dict-mode-length.js @@ -0,0 +1,18 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Author: Emilio Cobos Álvarez + */ +var BUGNUMBER = 1312948; +var summary = "Freezing a dictionary mode object with a length property should make Object.isFrozen report true"; + +print(BUGNUMBER + ": " + summary); + +/* Convert to dictionary mode */ +delete Array.prototype.slice; + +Object.freeze(Array.prototype); +assertEq(Object.isFrozen(Array.prototype), true); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/getter-name.js b/js/src/tests/non262/Array/getter-name.js new file mode 100644 index 0000000000..3829c729ba --- /dev/null +++ b/js/src/tests/non262/Array/getter-name.js @@ -0,0 +1,9 @@ +var BUGNUMBER = 1180290; +var summary = 'Array getters should have get prefix'; + +print(BUGNUMBER + ": " + summary); + +assertEq(Object.getOwnPropertyDescriptor(Array, Symbol.species).get.name, "get [Symbol.species]"); + +if (typeof reportCompare === 'function') + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/group-callback-evaluation.js b/js/src/tests/non262/Array/group-callback-evaluation.js new file mode 100644 index 0000000000..4fbb6467e7 --- /dev/null +++ b/js/src/tests/non262/Array/group-callback-evaluation.js @@ -0,0 +1,18 @@ +var array = [1, 2, 3]; + +var calls = 0; + +var grouped = Object.groupBy(array, () => { + calls++; + + return { + toString() { + return "a"; + } + } +}); + +assertEq(calls, 3); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Array/group-propertkey-is-length.js b/js/src/tests/non262/Array/group-propertkey-is-length.js new file mode 100644 index 0000000000..49eb512ec6 --- /dev/null +++ b/js/src/tests/non262/Array/group-propertkey-is-length.js @@ -0,0 +1,15 @@ +var array = [0]; + +var grouped = Object.groupBy(array, () => "length"); + +assertDeepEq(grouped, Object.create(null, { + length: { + value: [0], + writable: true, + enumerable: true, + configurable: true, + }, +})); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Array/group.js b/js/src/tests/non262/Array/group.js new file mode 100644 index 0000000000..9e89d1889d --- /dev/null +++ b/js/src/tests/non262/Array/group.js @@ -0,0 +1,88 @@ +function isNeg(x) { + if (Object.is(x, -0) || x < 0) { + return true; + } + return false; +} + +{ + const a1 = [-Infinity, -2, -1, -0, 0, 1, 2, Infinity]; + const expectedObj = { neg: [-Infinity, -2, -1, -0], pos: [0, 1, 2, Infinity] }; + Object.setPrototypeOf(expectedObj, null); + + const groupedArray = Object.groupBy(a1, x => isNeg(x) ? 'neg' : 'pos'); + const mappedArray = Map.groupBy(a1, x => isNeg(x) ? 'neg' : 'pos'); + + assertEq(Object.getPrototypeOf(groupedArray), null) + assertDeepEq(groupedArray, expectedObj); + assertDeepEq(mappedArray.get("neg"), expectedObj["neg"]); + assertDeepEq(mappedArray.get("pos"), expectedObj["pos"]); + + + const expectedObj2 = {"undefined": [1,2,3]} + Object.setPrototypeOf(expectedObj2, null); + assertDeepEq(Object.groupBy([1,2,3], () => {}), expectedObj2); + assertDeepEq(Object.groupBy([], () => {}), Object.create(null)); + assertDeepEq((Map.groupBy([1,2,3], () => {})).get(undefined), [1,2,3]); + assertEq((Map.groupBy([1,2,3], () => {})).size, 1); + + const negMappedArray = Map.groupBy(a1, x => isNeg(x) ? -0 : 0); + assertDeepEq(negMappedArray.get(0), a1); + assertDeepEq(negMappedArray.size, 1); + + assertThrowsInstanceOf(() => Object.groupBy([], undefined), TypeError); + assertThrowsInstanceOf(() => Object.groupBy([], null), TypeError); + assertThrowsInstanceOf(() => Object.groupBy([], 0), TypeError); + assertThrowsInstanceOf(() => Object.groupBy([], ""), TypeError); + assertThrowsInstanceOf(() => Map.groupBy([], undefined), TypeError); + assertThrowsInstanceOf(() => Map.groupBy([], null), TypeError); + assertThrowsInstanceOf(() => Map.groupBy([], 0), TypeError); + assertThrowsInstanceOf(() => Map.groupBy([], ""), TypeError); +} + +const array = [ 'test' ]; +Object.defineProperty(Map.prototype, 4, { + get() { + throw new Error('monkey-patched Map get call'); + }, + set(v) { + throw new Error('monkey-patched Map set call'); + }, + has(v) { + throw new Error('monkey-patched Map has call'); + } +}); + +const map1 = Map.groupBy(array, key => key.length); + +assertEq('test', map1.get(4)[0]) + +Object.defineProperty(Array.prototype, '4', { + set(v) { + throw new Error('user observable array set'); + }, + get() { + throw new Error('user observable array get'); + } +}); + +const map2 = Map.groupBy(array, key => key.length); +const arr = Object.groupBy(array, key => key.length); + +assertEq('test', map2.get(4)[0]) +assertEq('test', arr[4][0]) + +Object.defineProperty(Object.prototype, "foo", { + get() { throw new Error("user observable object get"); }, + set(v) { throw new Error("user observable object set"); } +}); +Object.groupBy([1, 2, 3], () => 'foo'); + +// Ensure property key is correctly accessed +count = 0; +p = Object.groupBy([1], () => ({ toString() { count++; return 10 } })); +assertEq(count, 1); +Map.groupBy([1], () => ({ toString() { count++; return 10 } })); +assertEq(count, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/non262/Array/includes-trailing-holes.js b/js/src/tests/non262/Array/includes-trailing-holes.js new file mode 100644 index 0000000000..b783cc36d8 --- /dev/null +++ b/js/src/tests/non262/Array/includes-trailing-holes.js @@ -0,0 +1,16 @@ +// Array with trailing hole as explicit "magic elements hole". +assertEq([,].includes(), true); +assertEq([,].includes(undefined), true); +assertEq([,].includes(undefined, 0), true); +assertEq([,].includes(null), false); +assertEq([,].includes(null, 0), false); + +// Array with trailing hole with no explicit "magic elements hole". +assertEq(Array(1).includes(), true); +assertEq(Array(1).includes(undefined), true); +assertEq(Array(1).includes(undefined, 0), true); +assertEq(Array(1).includes(null), false); +assertEq(Array(1).includes(null, 0), false); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/includes.js b/js/src/tests/non262/Array/includes.js new file mode 100644 index 0000000000..aa439571ce --- /dev/null +++ b/js/src/tests/non262/Array/includes.js @@ -0,0 +1,59 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 1069063; +var summary = "Implement Array.prototype.includes"; + +print(BUGNUMBER + ": " + summary); + +assertEq(typeof [].includes, "function"); +assertEq([].includes.length, 1); + +assertTrue([1, 2, 3].includes(2)); +assertTrue([1,,2].includes(2)); +assertTrue([1, 2, 3].includes(2, 1)); +assertTrue([1, 2, 3].includes(2, -2)); +assertTrue([1, 2, 3].includes(2, -100)); +assertTrue([Object, Function, Array].includes(Function)); +assertTrue([-0].includes(0)); +assertTrue([NaN].includes(NaN)); +assertTrue([,].includes()); +assertTrue(staticIncludes("123", "2")); +assertTrue(staticIncludes({length: 3, 1: 2}, 2)); +assertTrue(staticIncludes({length: 3, 1: 2, get 3(){throw ""}}, 2)); +assertTrue(staticIncludes({length: 3, get 1() {return 2}}, 2)); +assertTrue(staticIncludes({__proto__: {1: 2}, length: 3}, 2)); +assertTrue(staticIncludes(new Proxy([1], {get(){return 2}}), 2)); + +assertFalse([1, 2, 3].includes("2")); +assertFalse([1, 2, 3].includes(2, 2)); +assertFalse([1, 2, 3].includes(2, -1)); +assertFalse([undefined].includes(NaN)); +assertFalse([{}].includes({})); +assertFalse(staticIncludes({length: 3, 1: 2}, 2, 2)); +assertFalse(staticIncludes({length: 3, get 0(){delete this[1]}, 1: 2}, 2)); +assertFalse(staticIncludes({length: -100, 0: 1}, 1)); + +assertThrowsInstanceOf(() => staticIncludes(), TypeError); +assertThrowsInstanceOf(() => staticIncludes(null), TypeError); +assertThrowsInstanceOf(() => staticIncludes({get length(){throw TypeError()}}), TypeError); +assertThrowsInstanceOf(() => staticIncludes({length: 3, get 1() {throw TypeError()}}, 2), TypeError); +assertThrowsInstanceOf(() => staticIncludes({__proto__: {get 1() {throw TypeError()}}, length: 3}, 2), TypeError); +assertThrowsInstanceOf(() => staticIncludes(new Proxy([1], {get(){throw TypeError()}})), TypeError); + +function assertTrue(v) { + assertEq(v, true); +} + +function assertFalse(v) { + assertEq(v, false); +} + +function staticIncludes(o, v, f) { + return [].includes.call(o, v, f); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/index-with-null-character.js b/js/src/tests/non262/Array/index-with-null-character.js new file mode 100644 index 0000000000..51e71bc8a9 --- /dev/null +++ b/js/src/tests/non262/Array/index-with-null-character.js @@ -0,0 +1,18 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var testArray = [1, 2, 3] +assertEq(testArray['0' + '\0'], undefined); +assertEq(testArray['1' + '\0' + 'aaaa'], undefined) +assertEq(testArray['\0' + '2'], undefined); +assertEq(testArray['\0' + ' 2'], undefined); + +testArray['\0'] = 'hello'; +testArray[' \0'] = 'world'; +assertEq(testArray['\0'], 'hello'); +assertEq(testArray[' \0'], 'world'); + +if (typeof reportCompare == 'function') + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/indexOf-never-returns-negative-zero.js b/js/src/tests/non262/Array/indexOf-never-returns-negative-zero.js new file mode 100644 index 0000000000..0b39bf0a16 --- /dev/null +++ b/js/src/tests/non262/Array/indexOf-never-returns-negative-zero.js @@ -0,0 +1,4 @@ +assertEq([17].indexOf(17, -0), +0); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/indexOf-packed-array.js b/js/src/tests/non262/Array/indexOf-packed-array.js new file mode 100644 index 0000000000..97c2da8855 --- /dev/null +++ b/js/src/tests/non262/Array/indexOf-packed-array.js @@ -0,0 +1,40 @@ +function makeArray(array) { + var log = []; + Object.setPrototypeOf(array, new Proxy(Array.prototype, new Proxy({ + has(t, pk) { + log.push(`Has:${String(pk)}`); + return Reflect.has(t, pk); + }, + }, { + get(t, pk, r) { + if (pk in t) + return Reflect.get(t, pk, r); + throw new Error(`Unexpected trap "${pk}" called`); + } + }))); + return {array, log}; +} + + +var {array, log} = makeArray([1, null, 3]); +Array.prototype.indexOf.call(array, 100, { + valueOf() { + array.length = 0; + return 0; + } +}); +assertEqArray(log, ["Has:0", "Has:1", "Has:2"]); + + +var {array, log} = makeArray([5, undefined, 7]); +Array.prototype.lastIndexOf.call(array, 100, { + valueOf() { + array.length = 0; + return 2; + } +}); +assertEqArray(log, ["Has:2", "Has:1", "Has:0"]); + + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/isArray.js b/js/src/tests/non262/Array/isArray.js new file mode 100644 index 0000000000..b752ad54e4 --- /dev/null +++ b/js/src/tests/non262/Array/isArray.js @@ -0,0 +1,67 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +var global = this; +var otherGlobal = newGlobal(); + +var thisGlobal = () => global; +var alternateGlobals = (function(i) { + return () => (i++ % 2) === 0 ? global : otherGlobal; +})(0); + +function performTests(pickGlobal) +{ + // Base case. + assertEq(Array.isArray([]), true); + + // Simple case: proxy to an array. + var proxy = new (pickGlobal()).Proxy([], {}); + assertEq(Array.isArray(proxy), true); + + // Recursive proxy ultimately terminating in an array. + for (var i = 0; i < 10; i++) { + proxy = new (pickGlobal()).Proxy(proxy, {}); + assertEq(Array.isArray(proxy), true); + } + + // Revocable proxy to an array. + var revocable = (pickGlobal()).Proxy.revocable([], {}); + proxy = revocable.proxy; + assertEq(Array.isArray(proxy), true); + + // Recursive proxy ultimately terminating in a revocable proxy to an array. + for (var i = 0; i < 10; i++) { + proxy = new (pickGlobal()).Proxy(proxy, {}); + assertEq(Array.isArray(proxy), true); + } + + // Revoked proxy to (formerly) an array. + revocable.revoke(); + assertThrowsInstanceOf(() => Array.isArray(revocable.proxy), TypeError); + + // Recursive proxy ultimately terminating in a revoked proxy to an array. + assertThrowsInstanceOf(() => Array.isArray(proxy), TypeError); + +} + +performTests(thisGlobal); +performTests(alternateGlobals); + +function crossGlobalTest() +{ + var array = new otherGlobal.Array(); + + // Array from another global. + assertEq(Array.isArray(array), true); + + // Proxy to an array from another global. + assertEq(Array.isArray(new Proxy(array, {})), true); + + // Other-global proxy to an array from that selfsame global. + assertEq(Array.isArray(new otherGlobal.Proxy(array, {})), true); +} + +crossGlobalTest(); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/iterator_edge_cases.js b/js/src/tests/non262/Array/iterator_edge_cases.js new file mode 100644 index 0000000000..156aaba5f1 --- /dev/null +++ b/js/src/tests/non262/Array/iterator_edge_cases.js @@ -0,0 +1,50 @@ +// Test that we can't confuse %ArrayIteratorPrototype% for an +// ArrayIterator object. +function TestArrayIteratorPrototypeConfusion() { + var iter = [][Symbol.iterator](); + try { + iter.next.call(Object.getPrototypeOf(iter)) + throw new Error("Call did not throw"); + } catch (e) { + assertEq(e instanceof TypeError, true); + assertEq(e.message, "next method called on incompatible Array Iterator"); + } +} +TestArrayIteratorPrototypeConfusion(); + +// Tests that we can use %ArrayIteratorPrototype%.next on a +// cross-compartment iterator. +function TestArrayIteratorWrappers() { + var iter = [][Symbol.iterator](); + assertDeepEq(iter.next.call(newGlobal().eval('[5][Symbol.iterator]()')), + { value: 5, done: false }) +} +if (typeof newGlobal === "function") { + TestArrayIteratorWrappers(); +} + +// Tests that calling |next| on an array iterator after iteration has finished +// doesn't get the array's |length| property. +function TestIteratorNextGetLength() { + var lengthCalledTimes = 0; + var array = { + __proto__: Array.prototype, + get length() { + lengthCalledTimes += 1; + return { + valueOf() { + return 0; + } + }; + } + }; + var it = array[Symbol.iterator](); + it.next(); + it.next(); + assertEq(1, lengthCalledTimes); +} +TestIteratorNextGetLength(); + + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/join-01.js b/js/src/tests/non262/Array/join-01.js new file mode 100644 index 0000000000..3cc6cccd0d --- /dev/null +++ b/js/src/tests/non262/Array/join-01.js @@ -0,0 +1,83 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: + * Jeff Walden + */ + +//----------------------------------------------------------------------------- +print("ES5: Array.prototype.join"); + +/************** + * BEGIN TEST * + **************/ + +var count; +var stringifyCounter = { toString: function() { count++; return "obj"; } }; + +var arr = [1, 2, 3, 4, 5]; +assertEq(arr.join(), "1,2,3,4,5"); +assertEq(arr.join(","), "1,2,3,4,5"); +assertEq(arr.join(undefined), "1,2,3,4,5"); +assertEq(arr.join(4), "142434445"); +assertEq(arr.join(""), "12345"); + +count = 0; +assertEq(arr.join(stringifyCounter), "1obj2obj3obj4obj5"); +assertEq(count, 1); + +var holey = [1, 2, , 4, 5]; +assertEq(holey.join(), "1,2,,4,5"); +assertEq(holey.join(","), "1,2,,4,5"); +assertEq(holey.join(undefined), "1,2,,4,5"); +assertEq(holey.join(4), "14244445"); + +count = 0; +assertEq(holey.join(stringifyCounter), "1obj2objobj4obj5"); +assertEq(count, 1); + +var nully = [1, 2, 3, null, 5]; +assertEq(nully.join(), "1,2,3,,5"); +assertEq(nully.join(","), "1,2,3,,5"); +assertEq(nully.join(undefined), "1,2,3,,5"); +assertEq(nully.join(4), "14243445"); + +count = 0; +assertEq(nully.join(stringifyCounter), "1obj2obj3objobj5"); +assertEq(count, 1); + +var undefiney = [1, undefined, 3, 4, 5]; +assertEq(undefiney.join(), "1,,3,4,5"); +assertEq(undefiney.join(","), "1,,3,4,5"); +assertEq(undefiney.join(undefined), "1,,3,4,5"); +assertEq(undefiney.join(4), "14434445"); + +count = 0; +assertEq(undefiney.join(stringifyCounter), "1objobj3obj4obj5"); +assertEq(count, 1); + +var log = ''; +arr = {length: {valueOf: function () { log += "L"; return 2; }}, + 0: "x", 1: "z"}; +var sep = {toString: function () { log += "S"; return "y"; }}; +assertEq(Array.prototype.join.call(arr, sep), "xyz"); +assertEq(log, "LS"); + +var funky = + { + toString: function() + { + Array.prototype[1] = "chorp"; + Object.prototype[3] = "fnord"; + return "funky"; + } + }; +var trailingHoles = [0, funky, /* 2 */, /* 3 */,]; +assertEq(trailingHoles.join(""), "0funkyfnord"); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Array/join-no-has-trap.js b/js/src/tests/non262/Array/join-no-has-trap.js new file mode 100644 index 0000000000..16b8cbedb1 --- /dev/null +++ b/js/src/tests/non262/Array/join-no-has-trap.js @@ -0,0 +1,36 @@ +// Test that Array.prototype.join doesn't call the [[HasProperty]] internal +// method of objects. + +var log = []; +var array = []; +var proxy = new Proxy(array, new Proxy({}, { + get(t, trap, r) { + return (t, pk, ...more) => { + log.push(`${trap}:${String(pk)}`); + return Reflect[trap](t, pk, ...more); + }; + } +})); + +var result; + +result = Array.prototype.join.call(proxy); +assertEqArray(log, [ "get:length" ]); +assertEq(result, ""); + +log.length = 0; +array.push(1); + +result = Array.prototype.join.call(proxy); +assertEqArray(log, [ "get:length", "get:0" ]); +assertEq(result, "1"); + +log.length = 0; +array.push(2); + +result = Array.prototype.join.call(proxy); +assertEqArray(log, [ "get:length", "get:0", "get:1" ]); +assertEq(result, "1,2"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/lastIndexOf-never-returns-negative-zero.js b/js/src/tests/non262/Array/lastIndexOf-never-returns-negative-zero.js new file mode 100644 index 0000000000..296f87ec1f --- /dev/null +++ b/js/src/tests/non262/Array/lastIndexOf-never-returns-negative-zero.js @@ -0,0 +1,4 @@ +assertEq([17].lastIndexOf(17, -0), +0); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/length-01.js b/js/src/tests/non262/Array/length-01.js new file mode 100644 index 0000000000..4fe81e2b6e --- /dev/null +++ b/js/src/tests/non262/Array/length-01.js @@ -0,0 +1,71 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: + * Jeff Walden + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 600392; +var summary = + 'Object.preventExtensions([]).length = 0 should do nothing, not throw'; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + + +function testEmpty() +{ + var a = []; + assertEq(a.length, 0); + assertEq(Object.preventExtensions(a), a); + assertEq(a.length, 0); + a.length = 0; + assertEq(a.length, 0); +} +testEmpty(); + +function testEmptyStrict() +{ + "use strict"; + var a = []; + assertEq(a.length, 0); + assertEq(Object.preventExtensions(a), a); + assertEq(a.length, 0); + a.length = 0; + assertEq(a.length, 0); +} +testEmptyStrict(); + +function testNonEmpty() +{ + var a = [1, 2, 3]; + assertEq(a.length, 3); + assertEq(Object.preventExtensions(a), a); + assertEq(a.length, 3); + a.length = 0; + assertEq(a.length, 0); +} +testNonEmpty(); + +function testNonEmptyStrict() +{ + "use strict"; + var a = [1, 2, 3]; + assertEq(a.length, 3); + assertEq(Object.preventExtensions(a), a); + assertEq(a.length, 3); + a.length = 0; + assertEq(a.length, 0); +} +testNonEmptyStrict(); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Array/length-nonwritable-redefine-nop.js b/js/src/tests/non262/Array/length-nonwritable-redefine-nop.js new file mode 100644 index 0000000000..1d7fe32c8e --- /dev/null +++ b/js/src/tests/non262/Array/length-nonwritable-redefine-nop.js @@ -0,0 +1,70 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: + * Jeff Walden + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 858381; +var summary = "No-op array length redefinition"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var arr; + +// initializedLength == capacity == length +// 6 == 6 == 6 +arr = Object.defineProperty([0, 1, 2, 3, 4, 5], "length", { writable: false }); +Object.defineProperty(arr, "length", { value: 6 }); +Object.defineProperty(arr, "length", { writable: false }); +Object.defineProperty(arr, "length", { configurable: false }); +Object.defineProperty(arr, "length", { writable: false, configurable: false }); +Object.defineProperty(arr, "length", { writable: false, value: 6 }); +Object.defineProperty(arr, "length", { configurable: false, value: 6 }); +Object.defineProperty(arr, "length", { writable: false, configurable: false, value: 6 }); + +// initializedLength == capacity < length +// 6 == 6 < 8 +arr = Object.defineProperty([0, 1, 2, 3, 4, 5], "length", { value: 8, writable: false }); +Object.defineProperty(arr, "length", { value: 8 }); +Object.defineProperty(arr, "length", { writable: false }); +Object.defineProperty(arr, "length", { configurable: false }); +Object.defineProperty(arr, "length", { writable: false, configurable: false }); +Object.defineProperty(arr, "length", { writable: false, value: 8 }); +Object.defineProperty(arr, "length", { configurable: false, value: 8 }); +Object.defineProperty(arr, "length", { writable: false, configurable: false, value: 8 }); + +// initializedLength < capacity == length +// 7 < 8 == 8 +arr = Object.defineProperty([0, 1, 2, 3, 4, 5, 6, /* hole */, ], "length", + { value: 8, writable: false }); +Object.defineProperty(arr, "length", { value: 8 }); +Object.defineProperty(arr, "length", { writable: false }); +Object.defineProperty(arr, "length", { configurable: false }); +Object.defineProperty(arr, "length", { writable: false, configurable: false }); +Object.defineProperty(arr, "length", { writable: false, value: 8 }); +Object.defineProperty(arr, "length", { configurable: false, value: 8 }); +Object.defineProperty(arr, "length", { writable: false, configurable: false, value: 8 }); + +// initializedLength < capacity < length +// 3 < 6 < 8 +arr = Object.defineProperty([0, 1, 2], "length", { value: 8, writable: false }); +Object.defineProperty(arr, "length", { value: 8 }); +Object.defineProperty(arr, "length", { writable: false }); +Object.defineProperty(arr, "length", { configurable: false }); +Object.defineProperty(arr, "length", { writable: false, configurable: false }); +Object.defineProperty(arr, "length", { writable: false, value: 8 }); +Object.defineProperty(arr, "length", { configurable: false, value: 8 }); +Object.defineProperty(arr, "length", { writable: false, configurable: false, value: 8 }); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Array/length-set-object.js b/js/src/tests/non262/Array/length-set-object.js new file mode 100644 index 0000000000..bf80b592ea --- /dev/null +++ b/js/src/tests/non262/Array/length-set-object.js @@ -0,0 +1,68 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: + * Jeff Walden + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 657298; +var summary = 'Various quirks of setting array length properties to objects'; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function invokeConversionTwice1() +{ + var count = 0; + [].length = { valueOf: function() { count++; return 1; } }; + assertEq(count, 2); +} +invokeConversionTwice1(); + +function invokeConversionTwice2() +{ + var count = 0; + [].length = { toString: function() { count++; return 1; }, valueOf: null }; + assertEq(count, 2); +} +invokeConversionTwice2(); + +function dontOverwriteError1() +{ + try + { + [].length = { valueOf: {}, toString: {} }; + throw new Error("didn't throw a TypeError"); + } + catch (e) + { + assertEq(e instanceof TypeError, true, + "expected a TypeError running out of conversion options, got " + e); + } +} +dontOverwriteError1(); + +function dontOverwriteError2() +{ + try + { + [].length = { valueOf: function() { throw "error"; } }; + throw new Error("didn't throw a TypeError"); + } + catch (e) + { + assertEq(e, "error", "expected 'error' from failed conversion, got " + e); + } +} +dontOverwriteError2(); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Array/length-truncate-nonconfigurable-sparse.js b/js/src/tests/non262/Array/length-truncate-nonconfigurable-sparse.js new file mode 100644 index 0000000000..a51fd40898 --- /dev/null +++ b/js/src/tests/non262/Array/length-truncate-nonconfigurable-sparse.js @@ -0,0 +1,110 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: + * Jeff Walden + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 858381; +var summary = + "Array length redefinition behavior with non-configurable elements"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function addDataProperty(obj, prop, value, enumerable, configurable, writable) +{ + var desc = + { enumerable: enumerable, + configurable: configurable, + writable: writable, + value: value }; + Object.defineProperty(obj, prop, desc); +} + +function nonstrict() +{ + var arr = [0, , 2, , , 5]; + + addDataProperty(arr, 31415926, "foo", true, true, true); + addDataProperty(arr, 123456789, "bar", true, true, false); + addDataProperty(arr, 8675309, "qux", false, true, true); + addDataProperty(arr, 1735039, "eit", false, true, false); + addDataProperty(arr, 987654321, "fun", false, true, false); + + // non-array indexes to spice things up + addDataProperty(arr, "foopy", "sdfsd", false, false, false); + addDataProperty(arr, 4294967296, "psych", true, false, false); + addDataProperty(arr, 4294967295, "psych", true, false, false); + + addDataProperty(arr, 27182818, "eep", false, false, false); + + // Truncate...but only as far as possible. + arr.length = 1; + + assertEq(arr.length, 27182819); + + var props = Object.getOwnPropertyNames(arr).sort(); + var expected = + ["0", "2", "5", "1735039", "8675309", "27182818", + "foopy", "4294967296", "4294967295", "length"].sort(); + + assertEq(props.length, expected.length); + for (var i = 0; i < props.length; i++) + assertEq(props[i], expected[i], "unexpected property: " + props[i]); +} +nonstrict(); + +function strict() +{ + "use strict"; + + var arr = [0, , 2, , , 5]; + + addDataProperty(arr, 31415926, "foo", true, true, true); + addDataProperty(arr, 123456789, "bar", true, true, false); + addDataProperty(arr, 8675309, "qux", false, true, true); + addDataProperty(arr, 1735039, "eit", false, true, false); + addDataProperty(arr, 987654321, "fun", false, true, false); + + // non-array indexes to spice things up + addDataProperty(arr, "foopy", "sdfsd", false, false, false); + addDataProperty(arr, 4294967296, "psych", true, false, false); + addDataProperty(arr, 4294967295, "psych", true, false, false); + + addDataProperty(arr, 27182818, "eep", false, false, false); + + try + { + arr.length = 1; + throw new Error("didn't throw?!"); + } + catch (e) + { + assertEq(e instanceof TypeError, true, + "non-configurable property should trigger TypeError, got " + e); + } + + assertEq(arr.length, 27182819); + + var props = Object.getOwnPropertyNames(arr).sort(); + var expected = + ["0", "2", "5", "1735039", "8675309", "27182818", + "foopy", "4294967296", "4294967295", "length"].sort(); + + assertEq(props.length, expected.length); + for (var i = 0; i < props.length; i++) + assertEq(props[i], expected[i], "unexpected property: " + props[i]); +} +strict(); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Array/length-truncate-nonconfigurable.js b/js/src/tests/non262/Array/length-truncate-nonconfigurable.js new file mode 100644 index 0000000000..e9a66fe0ac --- /dev/null +++ b/js/src/tests/non262/Array/length-truncate-nonconfigurable.js @@ -0,0 +1,48 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: + * Jeff Walden + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 858381; +var summary = + "Array length redefinition behavior with non-configurable elements"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var arr = [0, 1, 2]; +Object.defineProperty(arr, 1, { configurable: false }); + +try +{ + Object.defineProperty(arr, "length", { value: 0, writable: false }); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, + "must throw TypeError when array truncation would have to remove " + + "non-configurable elements"); +} + +assertEq(arr.length, 2, "length is highest remaining index plus one"); + +var desc = Object.getOwnPropertyDescriptor(arr, "length"); +assertEq(desc !== undefined, true); + +assertEq(desc.value, 2); +assertEq(desc.writable, false); +assertEq(desc.enumerable, false); +assertEq(desc.configurable, false); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Array/length-truncate-with-indexed.js b/js/src/tests/non262/Array/length-truncate-with-indexed.js new file mode 100644 index 0000000000..9e4da812aa --- /dev/null +++ b/js/src/tests/non262/Array/length-truncate-with-indexed.js @@ -0,0 +1,101 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: + * Jeff Walden + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 858381; +var summary = + "Array length setting/truncating with non-dense, indexed elements"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function testTruncateDenseAndSparse() +{ + var arr; + + // initialized length 16, capacity same + arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + + // plus a sparse element + arr[987654321] = 987654321; + + // lop off the sparse element and half the dense elements, shrink capacity + arr.length = 8; + + assertEq(987654321 in arr, false); + assertEq(arr[987654321], undefined); + assertEq(arr.length, 8); +} +testTruncateDenseAndSparse(); + +function testTruncateSparse() +{ + // initialized length 8, capacity same + var arr = [0, 1, 2, 3, 4, 5, 6, 7]; + + // plus a sparse element + arr[987654321] = 987654321; + + // lop off the sparse element, leave initialized length/capacity unchanged + arr.length = 8; + + assertEq(987654321 in arr, false); + assertEq(arr[987654321], undefined); + assertEq(arr.length, 8); +} +testTruncateSparse(); + +function testTruncateDenseAndSparseShrinkCapacity() +{ + // initialized length 11, capacity...somewhat larger, likely 16 + var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + // plus a sparse element + arr[987654321] = 987654321; + + // lop off the sparse element, reduce initialized length, reduce capacity + arr.length = 8; + + assertEq(987654321 in arr, false); + assertEq(arr[987654321], undefined); + assertEq(arr.length, 8); +} +testTruncateDenseAndSparseShrinkCapacity(); + +function testTruncateSparseShrinkCapacity() +{ + // initialized length 8, capacity same + var arr = [0, 1, 2, 3, 4, 5, 6, 7]; + + // capacity expands to accommodate, initialized length remains same (not equal + // to capacity or length) + arr[15] = 15; + + // now no elements past initialized length + delete arr[15]; + + // ...except a sparse element + arr[987654321] = 987654321; + + // trims sparse element, doesn't change initialized length, shrinks capacity + arr.length = 8; + + assertEq(987654321 in arr, false); + assertEq(arr[987654321], undefined); + assertEq(arr.length, 8); +} +testTruncateSparseShrinkCapacity(); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Array/pop-empty-nonwritable.js b/js/src/tests/non262/Array/pop-empty-nonwritable.js new file mode 100644 index 0000000000..f42ca98f5c --- /dev/null +++ b/js/src/tests/non262/Array/pop-empty-nonwritable.js @@ -0,0 +1,32 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 858381; +var summary = 'Object.freeze([]).pop() must throw a TypeError'; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +try +{ + Object.freeze([]).pop(); + throw new Error("didn't throw"); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, + "should have thrown TypeError, instead got: " + e); +} + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Array/pop-no-has-trap.js b/js/src/tests/non262/Array/pop-no-has-trap.js new file mode 100644 index 0000000000..11bb93ddd0 --- /dev/null +++ b/js/src/tests/non262/Array/pop-no-has-trap.js @@ -0,0 +1,58 @@ +// Test that Array.prototype.pop doesn't call the [[HasProperty]] internal +// method of objects when retrieving the element at the last index. + +var log = []; +var array = []; +var proxy = new Proxy(array, new Proxy({}, { + get(t, trap, r) { + return (t, pk, ...more) => { + log.push(`${trap}:${String(pk)}`); + return Reflect[trap](t, pk, ...more); + }; + } +})); + +var result; + +result = Array.prototype.pop.call(proxy); +assertEqArray(log, [ + "get:length", + "set:length", "getOwnPropertyDescriptor:length", "defineProperty:length" +]); +assertEq(result, undefined); + +log.length = 0; +array.push(1); + +result = Array.prototype.pop.call(proxy); +assertEqArray(log, [ + "get:length", + "get:0", "deleteProperty:0", + "set:length", "getOwnPropertyDescriptor:length", "defineProperty:length" +]); +assertEq(result, 1); + +log.length = 0; +array.push(2, 3); + +result = Array.prototype.pop.call(proxy); +assertEqArray(log, [ + "get:length", + "get:1", "deleteProperty:1", + "set:length", "getOwnPropertyDescriptor:length", "defineProperty:length" +]); +assertEq(result, 3); + +log.length = 0; +array.push(4, 5); + +result = Array.prototype.pop.call(proxy); +assertEqArray(log, [ + "get:length", + "get:2", "deleteProperty:2", + "set:length", "getOwnPropertyDescriptor:length", "defineProperty:length" +]); +assertEq(result, 5); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/pop-nonarray-higher-elements.js b/js/src/tests/non262/Array/pop-nonarray-higher-elements.js new file mode 100644 index 0000000000..052eb4230f --- /dev/null +++ b/js/src/tests/non262/Array/pop-nonarray-higher-elements.js @@ -0,0 +1,91 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 909602; +var summary = + "Array.prototype.pop shouldn't touch elements greater than length on " + + "non-arrays"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function doTest(obj, index) +{ + // print("testing " + JSON.stringify(obj) + " with index " + index); + assertEq(Array.prototype.pop.call(obj), undefined); + assertEq(index in obj, true); + assertEq(obj[index], 42); +} + +// not-super-much-later element + +// non-zero length +function testPop1() +{ + var obj = { length: 2, 3: 42 }; + doTest(obj, 3); +} +for (var i = 0; i < 50; i++) + testPop1(); + +// zero length +function testPop2() +{ + var obj = { length: 0, 3: 42 }; + doTest(obj, 3); +} +for (var i = 0; i < 50; i++) + testPop2(); + +// much-later (but dense) element + +// non-zero length +function testPop3() +{ + var obj = { length: 2, 55: 42 }; + doTest(obj, 55); +} +for (var i = 0; i < 50; i++) + testPop3(); + +// zero length +function testPop4() +{ + var obj = { length: 0, 55: 42 }; + doTest(obj, 55); +} +for (var i = 0; i < 50; i++) + testPop4(); + +// much much much later (sparse) element + +// non-zero length +function testPop5() +{ + var obj = { length: 2, 65530: 42 }; + doTest(obj, 65530); +} +for (var i = 0; i < 50; i++) + testPop5(); + +// zero length +function testPop6() +{ + var obj = { length: 0, 65530: 42 }; + doTest(obj, 65530); +} +for (var i = 0; i < 50; i++) + testPop6(); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Array/redefine-length-accessor.js b/js/src/tests/non262/Array/redefine-length-accessor.js new file mode 100644 index 0000000000..339a3dd0fa --- /dev/null +++ b/js/src/tests/non262/Array/redefine-length-accessor.js @@ -0,0 +1,42 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var absent = {}; + +var getterValues = [absent, undefined, function(){}]; +var setterValues = [absent, undefined, function(){}]; +var configurableValues = [absent, true, false]; +var enumerableValues = [absent, true, false]; + +function CreateDescriptor(getter, setter, enumerable, configurable) { + var descriptor = {}; + if (getter !== absent) + descriptor.get = getter; + if (setter !== absent) + descriptor.set = setter; + if (configurable !== absent) + descriptor.configurable = configurable; + if (enumerable !== absent) + descriptor.enumerable = enumerable; + return descriptor; +} + +getterValues.forEach(function(getter) { + setterValues.forEach(function(setter) { + enumerableValues.forEach(function(enumerable) { + configurableValues.forEach(function(configurable) { + var descriptor = CreateDescriptor(getter, setter, enumerable, configurable); + if (!("get" in descriptor || "set" in descriptor)) + return; + + assertThrowsInstanceOf(function() { + Object.defineProperty([], "length", descriptor); + }, TypeError); + }); + }); + }); +}); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Array/redefine-length-frozen-array.js b/js/src/tests/non262/Array/redefine-length-frozen-array.js new file mode 100644 index 0000000000..ca3b43018b --- /dev/null +++ b/js/src/tests/non262/Array/redefine-length-frozen-array.js @@ -0,0 +1,26 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: + * Jeff Walden + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 866580; +var summary = "Assertion redefining length property of a frozen array"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var arr = Object.freeze([]); +Object.defineProperty(arr, "length", {}); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Array/redefine-length-frozen-dictionarymode-array.js b/js/src/tests/non262/Array/redefine-length-frozen-dictionarymode-array.js new file mode 100644 index 0000000000..bca6e0cd72 --- /dev/null +++ b/js/src/tests/non262/Array/redefine-length-frozen-dictionarymode-array.js @@ -0,0 +1,36 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: + * Jeff Walden + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 880591; +var summary = + "Assertion redefining length property of a frozen dictionary-mode array"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function convertToDictionaryMode(arr) +{ + Object.defineProperty(arr, 0, { configurable: true }); + Object.defineProperty(arr, 1, { configurable: true }); + delete arr[0]; +} + +var arr = []; +convertToDictionaryMode(arr); +Object.freeze(arr); +Object.defineProperty(arr, "length", {}); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Array/redefine-nonwritable-length-custom-conversion-call-counts.js b/js/src/tests/non262/Array/redefine-nonwritable-length-custom-conversion-call-counts.js new file mode 100644 index 0000000000..b77f396751 --- /dev/null +++ b/js/src/tests/non262/Array/redefine-nonwritable-length-custom-conversion-call-counts.js @@ -0,0 +1,45 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: + * Jeff Walden + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 866700; +var summary = "Assertion redefining non-writable length to a non-numeric value"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var count = 0; + +var convertible = + { + valueOf: function() + { + count++; + return 0; + } + }; + +var arr = []; +Object.defineProperty(arr, "length", { value: 0, writable: false }); + +Object.defineProperty(arr, "length", { value: convertible }); +assertEq(count, 2); + +Object.defineProperty(arr, "length", { value: convertible }); +assertEq(count, 4); + +assertEq(arr.length, 0); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Array/redefine-nonwritable-length-custom-conversion-throw.js b/js/src/tests/non262/Array/redefine-nonwritable-length-custom-conversion-throw.js new file mode 100644 index 0000000000..f3003a6bdb --- /dev/null +++ b/js/src/tests/non262/Array/redefine-nonwritable-length-custom-conversion-throw.js @@ -0,0 +1,58 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: + * Jeff Walden + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 866700; +var summary = "Assertion redefining non-writable length to a non-numeric value"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var count = 0; + +var convertible = + { + valueOf: function() + { + count++; + if (count > 2) + return 0; + throw new SyntaxError("fnord"); + } + }; + +var arr = []; +Object.defineProperty(arr, "length", { value: 0, writable: false }); + +try +{ + Object.defineProperty(arr, "length", + { + value: convertible, + writable: true, + configurable: true, + enumerable: true + }); + throw new Error("didn't throw"); +} +catch (e) +{ + assertEq(e instanceof SyntaxError, true, "expected SyntaxError, got " + e); +} + +assertEq(count, 1); +assertEq(arr.length, 0); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Array/redefine-nonwritable-length-nonnumeric.js b/js/src/tests/non262/Array/redefine-nonwritable-length-nonnumeric.js new file mode 100644 index 0000000000..aab9c1d5d2 --- /dev/null +++ b/js/src/tests/non262/Array/redefine-nonwritable-length-nonnumeric.js @@ -0,0 +1,32 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: + * Jeff Walden + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 866700; +var summary = "Assertion redefining non-writable length to a non-numeric value"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var arr = []; +Object.defineProperty(arr, "length", { value: 0, writable: false }); + +// Per Array's magical behavior, the value in the descriptor gets canonicalized +// *before* SameValue comparisons occur, so this shouldn't throw. +Object.defineProperty(arr, "length", { value: '' }); + +assertEq(arr.length, 0); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Array/regress-101488.js b/js/src/tests/non262/Array/regress-101488.js new file mode 100644 index 0000000000..f8372e7d92 --- /dev/null +++ b/js/src/tests/non262/Array/regress-101488.js @@ -0,0 +1,135 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Date: 24 September 2001 + * + * SUMMARY: Try assigning arr.length = new Number(n) + * From correspondence with Igor Bukanov + * See http://bugzilla.mozilla.org/show_bug.cgi?id=101488 + * + * Without the "new" keyword, assigning arr.length = Number(n) worked. + * But with it, Rhino was giving an error "Inappropriate array length" + * and SpiderMonkey was exiting without giving any error or return value - + * + * Comments on the Rhino code by igor@icesoft.no: + * + * jsSet_length requires that the new length value should be an instance + * of Number. But according to Ecma 15.4.5.1, item 12-13, an error should + * be thrown only if ToUint32(length_value) != ToNumber(length_value) + */ +//----------------------------------------------------------------------------- +var UBound = 0; +var BUGNUMBER = 101488; +var summary = 'Try assigning arr.length = new Number(n)'; +var status = ''; +var statusitems = []; +var actual = ''; +var actualvalues = []; +var expect= ''; +var expectedvalues = []; +var arr = []; + + +status = inSection(1); +arr = Array(); +tryThis('arr.length = new Number(1);'); +actual = arr.length; +expect = 1; +addThis(); + +status = inSection(2); +arr = Array(5); +tryThis('arr.length = new Number(1);'); +actual = arr.length; +expect = 1; +addThis(); + +status = inSection(3); +arr = Array(); +tryThis('arr.length = new Number(17);'); +actual = arr.length; +expect = 17; +addThis(); + +status = inSection(4); +arr = Array(5); +tryThis('arr.length = new Number(17);'); +actual = arr.length; +expect = 17; +addThis(); + + +/* + * Also try the above with the "new" keyword before Array(). + * Array() and new Array() should be equivalent, by ECMA 15.4.1.1 + */ +status = inSection(5); +arr = new Array(); +tryThis('arr.length = new Number(1);'); +actual = arr.length; +expect = 1; +addThis(); + +status = inSection(6); +arr = new Array(5); +tryThis('arr.length = new Number(1);'); +actual = arr.length; +expect = 1; +addThis(); + +arr = new Array(); +tryThis('arr.length = new Number(17);'); +actual = arr.length; +expect = 17; +addThis(); + +status = inSection(7); +arr = new Array(5); +tryThis('arr.length = new Number(17);'); +actual = arr.length; +expect = 17; +addThis(); + + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + + +function tryThis(s) +{ + try + { + eval(s); + } + catch(e) + { + // keep going + } +} + + +function addThis() +{ + statusitems[UBound] = status; + actualvalues[UBound] = actual; + expectedvalues[UBound] = expect; + UBound++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + for (var i=0; i var arr = new Array(0xFFFFFFFF) + * js> arr.length + * 4294967295 + * + * js> var arr = new Array(0x100000000) + * RangeError: invalid array length + * + * + * We'll try the largest possible array first, then a couple others. + * We're just testing that we don't crash on Array.sort(). + * + * Try to be good about memory by nulling each array variable after it is + * used. This will tell the garbage collector the memory is no longer needed. + * + * As of 2002-08-13, the JS shell runs out of memory no matter what we do, + * when trying to sort such large arrays. + * + * We only want to test that we don't CRASH on the sort. So it will be OK + * if we get the JS "out of memory" error. Note this terminates the test + * with exit code 3. Therefore we put + * + * |expectExitCode(3);| + * + * The only problem will arise if the JS shell ever DOES have enough memory + * to do the sort. Then this test will terminate with the normal exit code 0 + * and fail. + * + * Right now, I can't see any other way to do this, because "out of memory" + * is not a catchable error: it cannot be trapped with try...catch. + * + * + * FURTHER HEADACHE: Rhino can't seem to handle the largest array: it hangs. + * So we skip this case in Rhino. Here is correspondence with Igor Bukanov. + * He explains that Rhino isn't actually hanging; it's doing the huge sort: + * + * Philip Schwartau wrote: + * + * > Hi, + * > + * > I'm getting a graceful OOM message on trying to sort certain large + * > arrays. But if the array is too big, Rhino simply hangs. Note that ECMA + * > allows array lengths to be anything less than Math.pow(2,32), so the + * > arrays I'm sorting are legal. + * > + * > Note below, I'm getting an instantaneous OOM error on arr.sort() for LEN + * > = Math.pow(2, 30). So shouldn't I also get one for every LEN between + * > that and Math.pow(2, 32)? For some reason, I start to hang with 100% CPU + * > as LEN hits, say, Math.pow(2, 31) and higher. SpiderMonkey gives OOM + * > messages for all of these. Should I file a bug on this? + * + * Igor Bukanov wrote: + * + * This is due to different sorting algorithm Rhino uses when sorting + * arrays with length > Integer.MAX_VALUE. If length can fit Java int, + * Rhino first copies internal spare array to a temporary buffer, and then + * sorts it, otherwise it sorts array directly. In case of very spare + * arrays, that Array(big_number) generates, it is rather inefficient and + * generates OutOfMemory if length fits int. It may be worth in your case + * to optimize sorting to take into account array spareness, but then it + * would be a good idea to file a bug about ineficient sorting of spare + * arrays both in case of Rhino and SpiderMonkey as SM always uses a + * temporary buffer. + * + */ +//----------------------------------------------------------------------------- +var BUGNUMBER = 157652; +var summary = "Testing that Array.sort() doesn't crash on very large arrays"; +var expect = 'No Crash'; +var actual = 'No Crash'; + +printBugNumber(BUGNUMBER); +printStatus(summary); + +expectExitCode(0); +expectExitCode(5); + +try +{ + var a1=Array(0xFFFFFFFF); + a1.sort(); + a1 = null; + + var a2 = Array(0x40000000); + a2.sort(); + a2=null; + + var a3=Array(0x10000000/4); + a3.sort(); + a3=null; +} +catch(ex) +{ + // handle changed 1.9 branch behavior. see bug 422348 + expect = 'InternalError: allocation size overflow'; + actual = ex + ''; +} + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/Array/regress-178722.js b/js/src/tests/non262/Array/regress-178722.js new file mode 100644 index 0000000000..49c63bcbfe --- /dev/null +++ b/js/src/tests/non262/Array/regress-178722.js @@ -0,0 +1,127 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * + * Date: 06 November 2002 + * SUMMARY: arr.sort() should not output |undefined| when |arr| is empty + * See http://bugzilla.mozilla.org/show_bug.cgi?id=178722 + * + * ECMA-262 Ed.3: 15.4.4.11 Array.prototype.sort (comparefn) + * + * 1. Call the [[Get]] method of this object with argument "length". + * 2. Call ToUint32(Result(1)). + * 3. Perform an implementation-dependent sequence of calls to the [[Get]], + * [[Put]], and [[Delete]] methods of this object, etc. etc. + * 4. Return this object. + * + * + * Note that sort() is done in-place on |arr|. In other words, sort() is a + * "destructive" method rather than a "functional" method. The return value + * of |arr.sort()| and |arr| are the same object. + * + * If |arr| is an empty array, the return value of |arr.sort()| should be + * an empty array, not the value |undefined| as was occurring in bug 178722. + * + */ +//----------------------------------------------------------------------------- +var UBound = 0; +var BUGNUMBER = 178722; +var summary = 'arr.sort() should not output |undefined| when |arr| is empty'; +var status = ''; +var statusitems = []; +var actual = ''; +var actualvalues = []; +var expect= ''; +var expectedvalues = []; +var arr; + + +// create empty array or pseudo-array objects in various ways +var arr1 = Array(); +var arr2 = new Array(); +var arr3 = []; +var arr4 = [1]; +arr4.pop(); + + +status = inSection(1); +arr = arr1.sort(); +actual = arr instanceof Array && arr.length === 0 && arr === arr1; +expect = true; +addThis(); + +status = inSection(2); +arr = arr2.sort(); +actual = arr instanceof Array && arr.length === 0 && arr === arr2; +expect = true; +addThis(); + +status = inSection(3); +arr = arr3.sort(); +actual = arr instanceof Array && arr.length === 0 && arr === arr3; +expect = true; +addThis(); + +status = inSection(4); +arr = arr4.sort(); +actual = arr instanceof Array && arr.length === 0 && arr === arr4; +expect = true; +addThis(); + +// now do the same thing, with non-default sorting: +function g() {return 1;} + +status = inSection('1a'); +arr = arr1.sort(g); +actual = arr instanceof Array && arr.length === 0 && arr === arr1; +expect = true; +addThis(); + +status = inSection('2a'); +arr = arr2.sort(g); +actual = arr instanceof Array && arr.length === 0 && arr === arr2; +expect = true; +addThis(); + +status = inSection('3a'); +arr = arr3.sort(g); +actual = arr instanceof Array && arr.length === 0 && arr === arr3; +expect = true; +addThis(); + +status = inSection('4a'); +arr = arr4.sort(g); +actual = arr instanceof Array && arr.length === 0 && arr === arr4; +expect = true; +addThis(); + + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + + +function addThis() +{ + statusitems[UBound] = status; + actualvalues[UBound] = actual; + expectedvalues[UBound] = expect; + UBound++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus(summary); + + for (var i=0; i { + log.push(`${trap}:${String(pk)}`); + return Reflect[trap](t, pk, ...more); + }; + } +})); + +var result; + +result = Array.prototype.shift.call(proxy); +assertEqArray(log, [ + "get:length", + "set:length", "getOwnPropertyDescriptor:length", "defineProperty:length" +]); +assertEq(result, undefined); + +log.length = 0; +array.push(1); + +result = Array.prototype.shift.call(proxy); +assertEqArray(log, [ + "get:length", + "get:0", + "deleteProperty:0", + "set:length", "getOwnPropertyDescriptor:length", "defineProperty:length" +]); +assertEq(result, 1); + +log.length = 0; +array.push(2, 3); + +result = Array.prototype.shift.call(proxy); +assertEqArray(log, [ + "get:length", + "get:0", + "has:1", "get:1", "set:0", "getOwnPropertyDescriptor:0", "defineProperty:0", + "deleteProperty:1", + "set:length", "getOwnPropertyDescriptor:length", "defineProperty:length" +]); +assertEq(result, 2); + +log.length = 0; +array.push(4, 5); + +result = Array.prototype.shift.call(proxy); +assertEqArray(log, [ + "get:length", + "get:0", + "has:1", "get:1", "set:0", "getOwnPropertyDescriptor:0", "defineProperty:0", + "has:2", "get:2", "set:1", "getOwnPropertyDescriptor:1", "defineProperty:1", + "deleteProperty:2", + "set:length", "getOwnPropertyDescriptor:length", "defineProperty:length" +]); +assertEq(result, 3); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/shift_for_in.js b/js/src/tests/non262/Array/shift_for_in.js new file mode 100644 index 0000000000..1bbf2d9c2d --- /dev/null +++ b/js/src/tests/non262/Array/shift_for_in.js @@ -0,0 +1,13 @@ +var BUGNUMBER = 1247701; +var summary = 'Array.prototype.shift on a dense array with holes should update for-in enumeration properties.'; + +print(BUGNUMBER + ": " + summary); + +var x = ["a", , "b", , "c", "d" , "e", "f", "g"]; +for (var p in x) { + assertEq(p in x, true); + x.shift(); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/slice-sparse-with-large-index.js b/js/src/tests/non262/Array/slice-sparse-with-large-index.js new file mode 100644 index 0000000000..7fcf571e53 --- /dev/null +++ b/js/src/tests/non262/Array/slice-sparse-with-large-index.js @@ -0,0 +1,18 @@ +var array = []; +array[2**31 - 2] = "INT32_MAX - 1"; +array[2**31 - 1] = "INT32_MAX"; +array[2**31 - 0] = "INT32_MAX + 1"; +array[2**32 - 2] = "UINT32_MAX - 1"; +array[2**32 - 1] = "UINT32_MAX"; +array[2**32 - 0] = "UINT32_MAX + 1"; + +var copy = array.slice(); +assertEq(copy[2**31 - 2], "INT32_MAX - 1"); +assertEq(copy[2**31 - 1], "INT32_MAX"); +assertEq(copy[2**31 - 0], "INT32_MAX + 1"); +assertEq(copy[2**32 - 2], "UINT32_MAX - 1"); +assertEq(copy[2**32 - 1], undefined); +assertEq(copy[2**32 - 0], undefined); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/sort-01.js b/js/src/tests/non262/Array/sort-01.js new file mode 100644 index 0000000000..da90220aef --- /dev/null +++ b/js/src/tests/non262/Array/sort-01.js @@ -0,0 +1,23 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 604971; +var summary = 'array.sort compare-function gets incorrect this'; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +[1, 2, 3].sort(function() { "use strict"; assertEq(this, undefined); }); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Array/sort-array-with-holes-and-undefined.js b/js/src/tests/non262/Array/sort-array-with-holes-and-undefined.js new file mode 100644 index 0000000000..b77c6d3411 --- /dev/null +++ b/js/src/tests/non262/Array/sort-array-with-holes-and-undefined.js @@ -0,0 +1,32 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 664528; +var summary = + "Sorting an array containing only holes and |undefined| should move all " + + "|undefined| to the start of the array"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var a = [, , , undefined]; +a.sort(); + +assertEq(a.hasOwnProperty(0), true); +assertEq(a[0], undefined); +assertEq(a.hasOwnProperty(1), false); +assertEq(a.hasOwnProperty(2), false); +assertEq(a.hasOwnProperty(3), false); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Array/sort-delete-ascending-order.js b/js/src/tests/non262/Array/sort-delete-ascending-order.js new file mode 100644 index 0000000000..99df536df7 --- /dev/null +++ b/js/src/tests/non262/Array/sort-delete-ascending-order.js @@ -0,0 +1,37 @@ +// Calls Array.prototype.sort and tests that properties are deleted in the same order in the +// native and the self-hosted implementation. + +function createProxy() { + var deleted = []; + var proxy = new Proxy([, , 0], { + deleteProperty(t, pk){ + deleted.push(pk); + return delete t[pk]; + } + }); + + return {proxy, deleted}; +} + +function compareFn(a, b) { + return a < b ? -1 : a > b ? 1 : 0; +} + +// Sort an array without a comparator function. This calls the native sort implementation. + +var {proxy, deleted} = createProxy(); + +assertEqArray(deleted, []); +proxy.sort() +assertEqArray(deleted, ["1", "2"]); + +// Now sort an array with a comparator function. This calls the self-hosted sort implementation. + +var {proxy, deleted} = createProxy(); + +assertEqArray(deleted, []); +proxy.sort(compareFn); +assertEqArray(deleted, ["1", "2"]); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/sort-non-function.js b/js/src/tests/non262/Array/sort-non-function.js new file mode 100644 index 0000000000..91e3045932 --- /dev/null +++ b/js/src/tests/non262/Array/sort-non-function.js @@ -0,0 +1,22 @@ +// Array.prototype.sort throws if the comparator is neither undefined nor +// a callable object. + +// Use a zero length array, so we can provide any kind of callable object +// without worrying that the function is actually a valid comparator function. +const array = new Array(0); + +// Throws if the comparator is neither undefined nor callable. +for (let invalidComparator of [null, 0, true, Symbol(), {}, []]) { + assertThrowsInstanceOf(() => array.sort(invalidComparator), TypeError); +} + +// Doesn't throw if the comparator is undefined or a callable object. +for (let validComparator of [undefined, () => {}, Math.max, class {}, new Proxy(function(){}, {})]) { + array.sort(validComparator); +} + +// Also doesn't throw if no comparator was provided at all. +array.sort(); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Array/sort-typedarray-with-own-length.js b/js/src/tests/non262/Array/sort-typedarray-with-own-length.js new file mode 100644 index 0000000000..18e4ea5cd6 --- /dev/null +++ b/js/src/tests/non262/Array/sort-typedarray-with-own-length.js @@ -0,0 +1,33 @@ +function sortTypedArray(comparator) { + // Create a typed array with three elements, but also add an own "length" + // property with the value `2` to restrict the range of elements which + // will be sorted by Array.prototype.sort(). + var ta = new Int8Array([3, 2, 1]); + Object.defineProperty(ta, "length", {value: 2}); + + // Sort with Array.prototype.sort(), not %TypedArray%.prototype.sort()! + Array.prototype.sort.call(ta, comparator); + + return ta; +} + +// Comparators using the form |return a - b| are special-cased in +// Array.prototype.sort(). +function optimizedComparator(a, b) { + return a - b; +} + +// This comparator doesn't compile to the byte code sequence which gets +// special-cased in Array.prototype.sort(). +function nonOptimizedComparator(a, b) { + var d = a - b; + return d; +} + +// Both comparators should produce the same result. +assertEq(sortTypedArray(optimizedComparator).toString(), "2,3,1"); +assertEq(sortTypedArray(nonOptimizedComparator).toString(), "2,3,1"); + + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Array/sort_basics.js b/js/src/tests/non262/Array/sort_basics.js new file mode 100644 index 0000000000..e3011e5c48 --- /dev/null +++ b/js/src/tests/non262/Array/sort_basics.js @@ -0,0 +1,46 @@ +// Note: failed runs should include their "SEED" value in error messages, +// setting "const SEED" to that value will recreate the data from any such run. +const SEED = (Math.random() * 10) + 1; + +// Create an array filled with random values, 'size' is the desired length of +// the array and 'seed' is an initial value supplied to a pseudo-random number +// generator. +function genRandomArray(size, seed) { + return Array.from(XorShiftGenerator(seed, size)); +} + +function SortTest(size, seed) { + let arrOne = genRandomArray(size, seed); + let arrTwo = Array.from(arrOne); + let arrThree = Array.from(arrOne); + let typedArrays = [ + new Uint8Array(arrOne), + new Int32Array(arrOne), + new Float32Array(arrOne) + ]; + + let sorted = Array.from((Int32Array.from(arrOne)).sort()); + + // Test numeric comparators against typed array sort. + assertDeepEq(sorted, arrTwo.sort((x, y) => (x - y)), + `The array is not properly sorted! seed: ${SEED}`); + + // Use multiplication to kill comparator optimization and trigger + // self-hosted sorting. + assertDeepEq(sorted, arrThree.sort((x, y) => (1*x - 1*y)), + `The array is not properly sorted! seed: ${SEED}`); + + // Ensure that typed arrays are also sorted property. + for (typedArr of typedArrays) { + let sortedTypedArray = Array.prototype.sort.call(typedArr, (x, y) => (1*x - 1*y)) + assertDeepEq(sorted, Array.from(sortedTypedArray), + `The array is not properly sorted! seed: ${SEED}`); + } +} + +SortTest(2048, SEED); +SortTest(16, SEED); +SortTest(0, SEED); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/sort_holes.js b/js/src/tests/non262/Array/sort_holes.js new file mode 100644 index 0000000000..7424bd8894 --- /dev/null +++ b/js/src/tests/non262/Array/sort_holes.js @@ -0,0 +1,66 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// We should preserve holes when sorting sparce arrays. +// See bug: 1246860 + +function denseCount(arr) { + var c = 0; + for (var i = 0; i < arr.length; i++) + if (i in arr) + c++; + return c; +} + +let a = [,,,,,,,,,,,,,,,,,,,,{size: 1},{size: 2}]; +let b = [,,,,,,,,,,,,,,,,,,,,{size: 1},{size: 2}].sort(); +let c = [,,,,,,,,,,,,,,,,,,,,{size: 1},{size: 2}].sort((a, b) => {+a.size - +b.size}); + +assertEq(a.length, 22); +assertEq(denseCount(a), 2); +assertEq(a.length, b.length); +assertEq(b.length, c.length); +assertEq(denseCount(a), denseCount(b)); +assertEq(denseCount(b), denseCount(c)); + +let superSparce = new Array(5000); +superSparce[0] = 99; +superSparce[4000] = 0; +superSparce[4999] = -1; + +assertEq(superSparce.length, 5000); +assertEq(denseCount(superSparce), 3); + +superSparce.sort((a, b) => 1*a-b); +assertEq(superSparce.length, 5000); +assertEq(denseCount(superSparce), 3); +assertEq(superSparce[0], -1); +assertEq(superSparce[1], 0); +assertEq(superSparce[2], 99); + +let allHoles = new Array(2600); +assertEq(allHoles.length, 2600); +assertEq(denseCount(allHoles), 0); +allHoles.sort((a, b) => 1*a-b); +assertEq(allHoles.length, 2600); +assertEq(denseCount(allHoles), 0); + +let oneHole = new Array(2600); +oneHole[1399] = {size: 27}; +assertEq(oneHole.length, 2600); +assertEq(denseCount(oneHole), 1); +oneHole.sort((a, b) => {+a.size - +b.size}); +assertDeepEq(oneHole[0], {size: 27}); +assertEq(oneHole.length, 2600); +assertEq(denseCount(oneHole), 1); + +// Sealed objects should be sortable, including those with holes (so long +// as the holes appear at the end, so that they don't need to be moved). +assertDeepEq(Object.seal([0, 99, -1]).sort((x, y) => 1 * x - y), + Object.seal([-1, 0, 99])); + +assertDeepEq(Object.seal([1, 5, 4, , ,]).sort((x, y) => 1 * x - y), + Object.seal([1, 4, 5, , ,])); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Array/sort_native_string_nan.js b/js/src/tests/non262/Array/sort_native_string_nan.js new file mode 100644 index 0000000000..67ec08a015 --- /dev/null +++ b/js/src/tests/non262/Array/sort_native_string_nan.js @@ -0,0 +1,16 @@ + +var array = ["not-a-number", "also-not-a-number"]; +var copy = [...array]; + +// The sort comparator must be exactly equal to the bytecode pattern: +// +// JSOp::GetArg 0/1 +// JSOp::GetArg 1/0 +// JSOp::Sub +// JSOp::Return +array.sort(function(a, b) { return a - b; }); + +assertEqArray(array, copy); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Array/sort_proxy.js b/js/src/tests/non262/Array/sort_proxy.js new file mode 100644 index 0000000000..40ebb907bf --- /dev/null +++ b/js/src/tests/non262/Array/sort_proxy.js @@ -0,0 +1,38 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Ensure, via proxy, that only get, set, delete, has, and getOwnPropertyDescriptor +// are touched during sorting. + +const handler = { + set: function(target, prop, value) { + target[prop] = value; + return value; + }, + getPrototypeOf: () => { throw "You shouldn't touch getPrototypeOf!" }, + setPrototypeOf: () => { throw "You shouldn't touch setPrototypeOf!" }, + isExtensible: () => { throw "You shouldn't touch isExtensible!" }, + preventExtensions: () => { throw "You shouldn't touch preventExtensions!" }, + defineProperty: () => { throw "You shouldn't touch defineProperty!" }, + ownKeys: () => { throw "You shouldn't touch ownKeys!" }, + apply: () => { throw "You shouldn't touch apply!" }, + construct: () => { throw "You shouldn't touch construct!" }, +} + +function testArray(arr) { + let proxy = new Proxy(arr, handler) + + // The supplied comparators trigger a JavaScript implemented sort. + proxy.sort((x, y) => 1 * x - y); + arr.sort((x, y) => 1 * x - y); + + for (let i in arr) + assertEq(arr[i], proxy[i]); +} + +testArray([-1]); +testArray([5, -1, 2, 99]); +testArray([5, -1, , , , 2, 99]); +testArray([]); + +reportCompare(0, 0); diff --git a/js/src/tests/non262/Array/sort_small.js b/js/src/tests/non262/Array/sort_small.js new file mode 100644 index 0000000000..fa8b789e10 --- /dev/null +++ b/js/src/tests/non262/Array/sort_small.js @@ -0,0 +1,33 @@ +// Sort every possible permutation of some arrays. +function sortAllPermutations(data, comparefn) { + for (let permutation of Permutations(Array.from(data))) { + let sorted = (Array.from(permutation)).sort(comparefn); + for (let i in sorted) { + assertEq(sorted[i], data[i], + [`[${permutation}].sort(${comparefn})`, + `returned ${sorted}, expected ${data}`].join(' ')); + } + } +} + +let lex = [2112, "bob", "is", "my", "name"]; +let nans = [1/undefined, NaN, Number.NaN] + +let num1 = [-11, 0, 0, 100, 101]; +let num2 = [-11, 100, 201234.23, undefined, undefined]; + +sortAllPermutations(lex); +sortAllPermutations(nans); + +sortAllPermutations(nans, (x, y) => x - y); +// Multiplication kills comparator optimization. +sortAllPermutations(nans, (x, y) => (1*x - 1*y)); + +sortAllPermutations(num1, (x, y) => x - y); +sortAllPermutations(num1, (x, y) => (1*x - 1*y)); + +sortAllPermutations(num2, (x, y) => x - y); +sortAllPermutations(num2, (x, y) => (1*x - 1*y)); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/species.js b/js/src/tests/non262/Array/species.js new file mode 100644 index 0000000000..3669c286f6 --- /dev/null +++ b/js/src/tests/non262/Array/species.js @@ -0,0 +1,182 @@ +var BUGNUMBER = 1165052; +var summary = 'Use ArraySpeciesCreate in Array.prototype.{concat,filter,map,slice,splice}.'; + +print(BUGNUMBER + ": " + summary); + +function test(funcName, args, expectedLength, expectedLogs) { + // modified @@species + function FakeArray(n) { + this.length = n; + } + var a = [1, 2, 3, 4, 5]; + a.constructor = { + [Symbol.species]: FakeArray + }; + var b = a[funcName](...args); + assertEq(b.constructor, FakeArray); + + function FakeArrayWithSpecies(n) { + this.length = n; + } + FakeArrayWithSpecies[Symbol.species] = FakeArrayWithSpecies; + a = [1, 2, 3, 4, 5]; + a.constructor = FakeArrayWithSpecies; + b = a[funcName](...args); + assertEq(b.constructor, FakeArrayWithSpecies); + + function FakeArrayWithHook(n) { + return new Proxy(new FakeArray(n), { + set(that, name, value) { + logs += "set:" + name + ":" + value + ","; + return true; + }, + defineProperty(that, name, desc) { + logs += "define:" + name + ":" + desc.value + ":" + desc.configurable + ":" + desc.enumerable + ":" + desc.writable + ","; + return true; + } + }); + } + var logs = ""; + var ctorProxy = new Proxy({}, { + get(that, name) { + logs += "c-get:" + name.toString() + ","; + if (name == Symbol.species) + return FakeArrayWithHook; + + return undefined; + } + }); + a = new Proxy([1, 2, 3, 4, 5], { + get(that, name) { + logs += "get:" + name.toString() + ","; + if (name == "constructor") + return ctorProxy; + return that[name]; + } + }); + b = a[funcName](...args); + assertEq(b.constructor, FakeArray); + assertEq(Object.keys(b).sort().join(","), "length"); + assertEq(b.length, expectedLength); + assertEq(logs, expectedLogs); + + // no @@species + a = [1, 2, 3, 4, 5]; + a.constructor = FakeArray; + b = a[funcName](...args); + assertEq(b.constructor, Array); + + a = [1, 2, 3, 4, 5]; + a.constructor = { + [Symbol.species]: undefined + }; + b = a[funcName](...args); + assertEq(b.constructor, Array); + + a = [1, 2, 3, 4, 5]; + a.constructor = { + [Symbol.species]: null + }; + b = a[funcName](...args); + assertEq(b.constructor, Array); + + // invalid @@species + for (var species of [0, 1.1, true, false, "a", /a/, Symbol.iterator, [], {}]) { + a = [1, 2, 3, 4, 5]; + a.constructor = { + [Symbol.species]: species + }; + assertThrowsInstanceOf(() => a[funcName](...args), TypeError); + } + + // undefined constructor + a = [1, 2, 3, 4, 5]; + a.constructor = undefined; + b = a[funcName](...args); + assertEq(b.constructor, Array); + + // invalid constructor + for (var ctor of [null, 0, 1.1, true, false, "a", Symbol.iterator]) { + a = [1, 2, 3, 4, 5]; + a.constructor = ctor; + assertThrowsInstanceOf(() => a[funcName](...args), TypeError); + } + + // not an array + a = new Proxy({ + 0: 1, 1: 2, 2: 3, 3: 4, 4: 5, + length: 5, + [funcName]: Array.prototype[funcName] + }, { + get(that, name) { + assertEq(name !== "constructor", true); + return that[name]; + } + }); + b = a[funcName](...args); + assertEq(b.constructor, Array); + + // @@species from different global + var g = newGlobal(); + g.eval("function FakeArray(n) { this.length = n; }"); + a = [1, 2, 3, 4, 5]; + a.constructor = { + [Symbol.species]: g.FakeArray + }; + b = a[funcName](...args); + assertEq(b.constructor, g.FakeArray); + + a = [1, 2, 3, 4, 5]; + a.constructor = { + [Symbol.species]: g.Array + }; + b = a[funcName](...args); + assertEq(b.constructor, g.Array); + + // constructor from different global + g.eval("function FakeArrayWithSpecies(n) { this.length = n; }"); + g.eval("FakeArrayWithSpecies[Symbol.species] = FakeArrayWithSpecies;"); + a = [1, 2, 3, 4, 5]; + a.constructor = g.FakeArrayWithSpecies; + b = a[funcName](...args); + assertEq(b.constructor, g.FakeArrayWithSpecies); + + g.eval("var a = [1, 2, 3, 4, 5];"); + b = Array.prototype[funcName].apply(g.a, args); + assertEq(b.constructor, Array); + + // running in different global + b = g.a[funcName](...args); + assertEq(b.constructor, g.Array); + + // subclasses + // not-modified @@species + eval(` +class ${funcName}Class extends Array { +} +a = new ${funcName}Class(1, 2, 3, 4, 5); +b = a[funcName](...args); +assertEq(b.constructor, ${funcName}Class); +`); + + // modified @@species + eval(` +class ${funcName}Class2 extends Array { + static get [Symbol.species]() { + return Date; + } +} +a = new ${funcName}Class2(1, 2, 3, 4, 5); +b = a[funcName](...args); +assertEq(b.constructor, Date); +`); +} + +test("concat", [], 0, "get:concat,get:constructor,c-get:Symbol(Symbol.species),get:Symbol(Symbol.isConcatSpreadable),get:length,get:0,define:0:1:true:true:true,get:1,define:1:2:true:true:true,get:2,define:2:3:true:true:true,get:3,define:3:4:true:true:true,get:4,define:4:5:true:true:true,set:length:5,"); +test("filter", [x => x % 2], 0, "get:filter,get:length,get:constructor,c-get:Symbol(Symbol.species),get:0,define:0:1:true:true:true,get:1,get:2,define:1:3:true:true:true,get:3,get:4,define:2:5:true:true:true,"); +test("map", [x => x * 2], 5, "get:map,get:length,get:constructor,c-get:Symbol(Symbol.species),get:0,define:0:2:true:true:true,get:1,define:1:4:true:true:true,get:2,define:2:6:true:true:true,get:3,define:3:8:true:true:true,get:4,define:4:10:true:true:true,"); +test("slice", [], 5, "get:slice,get:length,get:constructor,c-get:Symbol(Symbol.species),get:0,define:0:1:true:true:true,get:1,define:1:2:true:true:true,get:2,define:2:3:true:true:true,get:3,define:3:4:true:true:true,get:4,define:4:5:true:true:true,set:length:5,"); +test("splice", [0, 5], 5, "get:splice,get:length,get:constructor,c-get:Symbol(Symbol.species),get:0,define:0:1:true:true:true,get:1,define:1:2:true:true:true,get:2,define:2:3:true:true:true,get:3,define:3:4:true:true:true,get:4,define:4:5:true:true:true,set:length:5,"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/splice-return-array-elements-defined-not-set.js b/js/src/tests/non262/Array/splice-return-array-elements-defined-not-set.js new file mode 100644 index 0000000000..2f5eca610d --- /dev/null +++ b/js/src/tests/non262/Array/splice-return-array-elements-defined-not-set.js @@ -0,0 +1,46 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 668024; +var summary = + 'Array.prototype.splice should define, not set, the elements of the array ' + + 'it returns'; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +Object.defineProperty(Object.prototype, 2, + { + set: function(v) + { + throw new Error("setter on Object.prototype called!"); + }, + get: function() { return "fnord"; }, + enumerable: false, + configurable: true + }); + +var arr = [0, 1, 2, 3, 4, 5]; +var removed = arr.splice(0, 6); + +assertEq(arr.length, 0); +assertEq(removed.length, 6); +assertEq(removed[0], 0); +assertEq(removed[1], 1); +assertEq(removed[2], 2); +assertEq(removed[3], 3); +assertEq(removed[4], 4); +assertEq(removed[5], 5); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Array/splice-species-changes-length.js b/js/src/tests/non262/Array/splice-species-changes-length.js new file mode 100644 index 0000000000..0e4ed32b01 --- /dev/null +++ b/js/src/tests/non262/Array/splice-species-changes-length.js @@ -0,0 +1,48 @@ +// Case 1: splice() removes an element from the array. +{ + let array = []; + array.push(0, 1, 2); + + array.constructor = { + [Symbol.species]: function(n) { + // Increase the initialized length of the array. + array.push(3, 4, 5); + + // Make the length property non-writable. + Object.defineProperty(array, "length", {writable: false}); + + return new Array(n); + } + } + + assertThrowsInstanceOf(() => Array.prototype.splice.call(array, 0, 1), TypeError); + + assertEq(array.length, 6); + assertEqArray(array, [1, 2, /* hole */, 3, 4, 5]); +} + +// Case 2: splice() adds an element to the array. +{ + let array = []; + array.push(0, 1, 2); + + array.constructor = { + [Symbol.species]: function(n) { + // Increase the initialized length of the array. + array.push(3, 4, 5); + + // Make the length property non-writable. + Object.defineProperty(array, "length", {writable: false}); + + return new Array(n); + } + } + + assertThrowsInstanceOf(() => Array.prototype.splice.call(array, 0, 0, 123), TypeError); + + assertEq(array.length, 6); + assertEqArray(array, [123, 0, 1, 2, 4, 5]); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/splice-suppresses-unvisited-indexes.js b/js/src/tests/non262/Array/splice-suppresses-unvisited-indexes.js new file mode 100644 index 0000000000..717116fa0a --- /dev/null +++ b/js/src/tests/non262/Array/splice-suppresses-unvisited-indexes.js @@ -0,0 +1,61 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 668024; +var summary = + 'Array.prototype.splice, when it deletes elements, should make sure any ' + + 'deleted but not visited elements are suppressed from subsequent enumeration'; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var arr = [0, 1, 2, 3, 4, 5, , 7]; + +var seen = []; +var sawOneBeforeThree = true; +for (var p in arr) +{ + if (p === "1") + { + // The order of enumeration of properties is unspecified, so technically, + // it would be kosher to enumerate "1" last, say, such that all properties + // in the array actually were enumerated, including an index which splice + // would delete. Don't flag that case as a failure. (SpiderMonkey doesn't + // do this, and neither do any of the other browser engines, but it is + // permissible behavior.) + if (seen.indexOf("3") >= 0) + { + sawOneBeforeThree = false; + break; + } + + arr.splice(2, 3); + } + + seen.push(p); +} + +if (sawOneBeforeThree) +{ + // ES5 12.6.4 states: + // + // If a property that has not yet been visited during enumeration is + // deleted, then it will not be visited. + // + // So if we haven't seen "3" by the time we see "1", the splice call above + // will delete "3", and therefore we must not see it. + assertEq(seen.indexOf("3"), -1); +} + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Array/to-length.js b/js/src/tests/non262/Array/to-length.js new file mode 100644 index 0000000000..d6b4c6d7cd --- /dev/null +++ b/js/src/tests/non262/Array/to-length.js @@ -0,0 +1,40 @@ +const max = Number.MAX_SAFE_INTEGER; + +assertEq(Array.prototype.indexOf.call({length: Infinity, [max - 1]: 'test'}, 'test', max - 3), max - 1); +assertEq(Array.prototype.lastIndexOf.call({length: Infinity, [max - 2]: 'test', [max - 1]: 'test2'}, 'test'), max - 2); + +// ToLength doesn't truncate Infinity to zero, so the callback should be invoked +assertThrowsValue(() => Array.prototype.every.call({length: Infinity, [0]: undefined}, () => { throw "invoked" }), "invoked"); +assertThrowsValue(() => Array.prototype.some.call({length: Infinity, [0]: undefined}, () => { throw "invoked" }), "invoked"); +// Timeout before calling our callback +// assertThrowsValue(() => Array.prototype.sort.call({length: Infinity}, () => { throw "invoked" }), "invoked"); +assertThrowsValue(() => Array.prototype.forEach.call({length: Infinity, [0]: undefined}, () => { throw "invoked" }), "invoked"); +assertThrowsValue(() => Array.prototype.filter.call({length: Infinity, [0]: undefined}, () => { throw "invoked" }), "invoked"); +assertThrowsValue(() => Array.prototype.reduce.call({length: Infinity, [0]: undefined, [1]: undefined}, () => { throw "invoked" }), "invoked"); +assertThrowsValue(() => Array.prototype.reduceRight.call({length: Infinity, [max - 1]: undefined, [max - 2]: undefined}, () => { throw "invoked" }), "invoked"); +assertThrowsValue(() => Array.prototype.find.call({length: Infinity}, () => { throw "invoked" }), "invoked"); +assertThrowsValue(() => Array.prototype.findIndex.call({length: Infinity}, () => { throw "invoked" }), "invoked"); +assertThrowsValue(() => Array.prototype.fill.call({length: Infinity, set "0"(v) { throw "invoked"; }}, () => { throw "invoked" }), "invoked"); +assertThrowsValue(() => Array.prototype.copyWithin.call({length: Infinity, get [max - 2]() { throw "invoked"; }}, max - 2, max - 2), "invoked"); + +assertEq(Array.prototype.includes.call({length: Infinity, [max - 1]: "test"}, "test", max - 3), true); + +// Invoking the Array constructor with MAX_SAFE_INTEGER will throw, 0 won't +assertThrowsInstanceOf(() => Array.from({length: Infinity}), RangeError); + +// Make sure ArraySpeciesCreate is called with ToLength applied to the length property +var proxy = new Proxy([], { + get(target, property) { + if (property === "length") + return Infinity; + + assertEq(property, "constructor"); + function fakeConstructor(length) { assertEq(length, max); throw "invoked"; }; + fakeConstructor[Symbol.species] = fakeConstructor; + return fakeConstructor; + } +}) +assertThrowsValue(() => Array.prototype.map.call(proxy, () => { }), "invoked"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/toLocaleString-01.js b/js/src/tests/non262/Array/toLocaleString-01.js new file mode 100644 index 0000000000..458283e635 --- /dev/null +++ b/js/src/tests/non262/Array/toLocaleString-01.js @@ -0,0 +1,36 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: + * Jeff Walden + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 562446; +var summary = 'ES5: Array.prototype.toLocaleString'; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var o; + +o = { length: 2, 0: 7, 1: { toLocaleString: function() { return "baz" } } }; +assertEq(Array.prototype.toLocaleString.call(o), "7,baz"); + +o = {}; +assertEq(Array.prototype.toLocaleString.call(o), ""); + +var log = ''; +arr = {length: {valueOf: function () { log += "L"; return 2; }}, + 0: "x", 1: "z"}; +assertEq(Array.prototype.toLocaleString.call(arr), "x,z"); +assertEq(log, "L"); + +/******************************************************************************/ + +reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Array/toLocaleString-nointl.js b/js/src/tests/non262/Array/toLocaleString-nointl.js new file mode 100644 index 0000000000..b0cee83049 --- /dev/null +++ b/js/src/tests/non262/Array/toLocaleString-nointl.js @@ -0,0 +1,26 @@ +if (typeof Intl !== "object") { + const localeSep = [,,].toLocaleString(); + + const obj = { + toLocaleString() { + assertEq(arguments.length, 0); + return "pass"; + } + }; + + // Ensure no arguments are passed to the array elements. + // - Single element case. + assertEq([obj].toLocaleString(), "pass"); + // - More than one element. + assertEq([obj, obj].toLocaleString(), "pass" + localeSep + "pass"); + + // Ensure no arguments are passed to the array elements even if supplied. + const locales = {}, options = {}; + // - Single element case. + assertEq([obj].toLocaleString(locales, options), "pass"); + // - More than one element. + assertEq([obj, obj].toLocaleString(locales, options), "pass" + localeSep + "pass"); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/toLocaleString.js b/js/src/tests/non262/Array/toLocaleString.js new file mode 100644 index 0000000000..4a16cb4a49 --- /dev/null +++ b/js/src/tests/non262/Array/toLocaleString.js @@ -0,0 +1,14 @@ +"use strict"; + +Object.defineProperty(String.prototype, "toLocaleString", { + get() { + assertEq(typeof this, "string"); + + return function() { return typeof this; }; + } +}) + +assertEq(["test"].toLocaleString(), "string"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/toSpliced-dense.js b/js/src/tests/non262/Array/toSpliced-dense.js new file mode 100644 index 0000000000..9671f55bfc --- /dev/null +++ b/js/src/tests/non262/Array/toSpliced-dense.js @@ -0,0 +1,127 @@ +// |reftest| + +const startIndices = [ + -10, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 10, +]; + +const deleteCounts = [ + 0, 1, 2, 3, 4, 5, 10, +]; + +const insertCounts = [ + 0, 1, 2, 3, 4, 5, 10, +]; + +const itemsList = insertCounts.map(count => { + return new Array(count).fill(0); +}); + +const arrays = [ + // Dense no holes. + [], + [1], + [1,2], + [1,2,3], + [1,2,3,4], + [1,2,3,4,5,6,7,8], + + // Dense trailing holes. + [,], + [1,,], + [1,2,,], + [1,2,3,,], + [1,2,3,4,,], + [1,2,3,4,5,6,7,8,,], + + // Dense leading holes. + [,], + [,1], + [,1,2], + [,1,2,3], + [,1,2,3,4], + [,1,2,3,4,5,6,7,8], + + // Dense with holes. + [1,,3], + [1,2,,4], + [1,,3,,5,6,,8], +]; + +const objects = arrays.map(array => { + let obj = { + length: array.length, + }; + for (let i = 0; i < array.length; ++i) { + if (i in array) { + obj[i] = array[i]; + } + } + return obj; +}); + +const objectsWithLargerDenseInitializedLength = arrays.map(array => { + let obj = { + length: array.length, + }; + for (let i = 0; i < array.length; ++i) { + if (i in array) { + obj[i] = array[i]; + } + } + + // Add some extra dense elements after |length|. + for (let i = 0; i < 5; ++i) { + obj[array.length + i] = "extra"; + } + + return obj; +}); + +const thisValues = [ + ...arrays, + ...objects, + ...objectsWithLargerDenseInitializedLength, +]; + +for (let thisValue of thisValues) { + for (let startIndex of startIndices) { + for (let deleteCount of deleteCounts) { + for (let items of itemsList) { + let res = Array.prototype.toSpliced.call(thisValue, startIndex, deleteCount, ...items); + + // Array.prototype.toSpliced(), steps 3-6. + let actualStart; + if (startIndex < 0) { + actualStart = Math.max(thisValue.length + startIndex, 0); + } else { + actualStart = Math.min(startIndex, thisValue.length); + } + + // Array.prototype.toSpliced(), step 10. + let actualDeleteCount = Math.min(Math.max(0, deleteCount), thisValue.length - actualStart); + + let newLength = thisValue.length + items.length - actualDeleteCount; + assertEq(res.length, newLength); + + for (let i = 0; i < actualStart; ++i) { + assertEq(Object.hasOwn(res, i), true); + assertEq(res[i], thisValue[i]); + } + + for (let i = 0; i < items.length; ++i) { + assertEq(Object.hasOwn(res, actualStart + i), true); + assertEq(res[actualStart + i], items[i]); + } + + for (let i = 0; i < newLength - actualStart - items.length; ++i) { + assertEq(Object.hasOwn(res, actualStart + items.length + i), true); + assertEq(res[actualStart + items.length + i], + thisValue[actualStart + actualDeleteCount + i]); + } + } + } + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Array/toSpliced.js b/js/src/tests/non262/Array/toSpliced.js new file mode 100644 index 0000000000..926b032f38 --- /dev/null +++ b/js/src/tests/non262/Array/toSpliced.js @@ -0,0 +1,27 @@ +// |reftest| + +Object.defineProperty(Array.prototype, 0, { + set() { + throw "bad 0"; + }, +}); + +Object.defineProperty(Array.prototype, 1, { + set() { + throw "bad 1"; + }, +}); + +assertDeepEq([].toSpliced(0, 0, 1), [1]); + +assertDeepEq([0].toSpliced(0, 0, 0), [0, 0]); +assertDeepEq([0].toSpliced(0, 0, 1), [1, 0]); +assertDeepEq([0].toSpliced(0, 1, 0), [0]); +assertDeepEq([0].toSpliced(0, 1, 1), [1]); +assertDeepEq([0].toSpliced(1, 0, 0), [0, 0]); +assertDeepEq([0].toSpliced(1, 0, 1), [0, 1]); +assertDeepEq([0].toSpliced(1, 1, 0), [0, 0]); +assertDeepEq([0].toSpliced(1, 1, 1), [0, 1]); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Array/toString-01.js b/js/src/tests/non262/Array/toString-01.js new file mode 100644 index 0000000000..a92fe6369b --- /dev/null +++ b/js/src/tests/non262/Array/toString-01.js @@ -0,0 +1,52 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: + * Jeff Walden + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 562446; +var summary = 'ES5: Array.prototype.toString'; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var o; + +o = { join: function() { assertEq(arguments.length, 0); return "ohai"; } }; +assertEq(Array.prototype.toString.call(o), "ohai"); + +o = {}; +assertEq(Array.prototype.toString.call(o), "[object Object]"); + +Array.prototype.join = function() { return "kthxbai"; }; +assertEq(Array.prototype.toString.call([]), "kthxbai"); + +o = { join: 17 }; +assertEq(Array.prototype.toString.call(o), "[object Object]"); + +o = { get join() { throw 42; } }; +try +{ + var str = Array.prototype.toString.call(o); + assertEq(true, false, + "expected an exception calling [].toString on an object with a " + + "join getter that throws, got " + str + " instead"); +} +catch (e) +{ + assertEq(e, 42, + "expected thrown e === 42 when calling [].toString on an object " + + "with a join getter that throws, got " + e); +} + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Array/unscopables.js b/js/src/tests/non262/Array/unscopables.js new file mode 100644 index 0000000000..de970ca1bd --- /dev/null +++ b/js/src/tests/non262/Array/unscopables.js @@ -0,0 +1,61 @@ +let Array_unscopables = Array.prototype[Symbol.unscopables]; + +let desc = Reflect.getOwnPropertyDescriptor(Array.prototype, Symbol.unscopables); +assertDeepEq(desc, { + value: Array_unscopables, + writable: false, + enumerable: false, + configurable: true +}); + +assertEq(Reflect.getPrototypeOf(Array_unscopables), null); + +let desc2 = Object.getOwnPropertyDescriptor(Array_unscopables, "values"); +assertDeepEq(desc2, { + value: true, + writable: true, + enumerable: true, + configurable: true +}); + +let keys = Reflect.ownKeys(Array_unscopables); + +// FIXME: Once bug 1826643 is fixed, change this test so that all +// the keys are in alphabetical order +let expectedKeys = ["at", + "copyWithin", + "entries", + "fill", + "find", + "findIndex", + "findLast", + "findLastIndex", + "flat", + "flatMap", + "includes", + "keys", + "toReversed", + "toSorted", + "toSpliced", + "values"]; + +assertDeepEq(keys, expectedKeys); + +for (let key of keys) + assertEq(Array_unscopables[key], true); + +// Test that it actually works +assertThrowsInstanceOf(() => { + with ([]) { + return entries; + } +}, ReferenceError); + +{ + let fill = 33; + with (Array.prototype) { + assertEq(fill, 33); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/non262/Array/unshift-01.js b/js/src/tests/non262/Array/unshift-01.js new file mode 100644 index 0000000000..fbae3294a7 --- /dev/null +++ b/js/src/tests/non262/Array/unshift-01.js @@ -0,0 +1,44 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 614070; +var summary = 'Array.prototype.unshift without args'; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +// ES6 ToLength clamps length values to 2^53 - 1. +var MAX_LENGTH = 2**53 - 1; + +var a = {}; +a.length = MAX_LENGTH + 1; +assertEq([].unshift.call(a), MAX_LENGTH); +assertEq(a.length, MAX_LENGTH); + +function testGetSet(len, expected) { + var newlen; + var a = { get length() { return len; }, set length(v) { newlen = v; } }; + var res = [].unshift.call(a); + assertEq(res, expected); + assertEq(newlen, expected); +} + +testGetSet(0, 0); +testGetSet(10, 10); +testGetSet("1", 1); +testGetSet(null, 0); +testGetSet(MAX_LENGTH + 2, MAX_LENGTH); +testGetSet(-5, 0); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Array/unshift-with-enumeration.js b/js/src/tests/non262/Array/unshift-with-enumeration.js new file mode 100644 index 0000000000..fbf451b8cc --- /dev/null +++ b/js/src/tests/non262/Array/unshift-with-enumeration.js @@ -0,0 +1,18 @@ +function f(array, method, args) { + var called = false; + var keys = []; + for (var key in array) { + keys.push(key); + if (!called) { + called = true; + Reflect.apply(method, array, args); + } + } + return keys; +} + +assertEqArray(f([1, /* hole */, 3], Array.prototype.unshift, [0]), ["0"]); +assertEqArray(f([1, /* hole */, 3], Array.prototype.splice, [0, 0, 0]), ["0"]); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Array/values.js b/js/src/tests/non262/Array/values.js new file mode 100644 index 0000000000..902a668123 --- /dev/null +++ b/js/src/tests/non262/Array/values.js @@ -0,0 +1,20 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +if (Array.prototype.values) { + assertEq(Array.prototype.values, Array.prototype[Symbol.iterator]); + assertEq(Array.prototype.values.name, "values"); + assertEq(Array.prototype.values.length, 0); + + function valuesUnscopeable() { + var values = "foo"; + with ([1, 2, 3]) { + assertEq(indexOf, Array.prototype.indexOf); + assertEq(values, "foo"); + } + } + valuesUnscopeable(); +} + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Array/with-dense.js b/js/src/tests/non262/Array/with-dense.js new file mode 100644 index 0000000000..4f457fbedd --- /dev/null +++ b/js/src/tests/non262/Array/with-dense.js @@ -0,0 +1,103 @@ +// |reftest| + +const indices = [ + -10, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 10, +]; + +const arrays = [ + // Dense no holes. + [], + [1], + [1,2], + [1,2,3], + [1,2,3,4], + [1,2,3,4,5,6,7,8], + + // Dense trailing holes. + [,], + [1,,], + [1,2,,], + [1,2,3,,], + [1,2,3,4,,], + [1,2,3,4,5,6,7,8,,], + + // Dense leading holes. + [,], + [,1], + [,1,2], + [,1,2,3], + [,1,2,3,4], + [,1,2,3,4,5,6,7,8], + + // Dense with holes. + [1,,3], + [1,2,,4], + [1,,3,,5,6,,8], +]; + +const objects = arrays.map(array => { + let obj = { + length: array.length, + }; + for (let i = 0; i < array.length; ++i) { + if (i in array) { + obj[i] = array[i]; + } + } + return obj; +}); + +const objectsWithLargerDenseInitializedLength = arrays.map(array => { + let obj = { + length: array.length, + }; + for (let i = 0; i < array.length; ++i) { + if (i in array) { + obj[i] = array[i]; + } + } + + // Add some extra dense elements after |length|. + for (let i = 0; i < 5; ++i) { + obj[array.length + i] = "extra"; + } + + return obj; +}); + +const thisValues = [ + ...arrays, + ...objects, + ...objectsWithLargerDenseInitializedLength, +]; + +const replacement = {}; + +for (let thisValue of thisValues) { + for (let index of indices) { + let actualIndex = index; + if (actualIndex < 0) { + actualIndex += thisValue.length; + } + + if (actualIndex < 0 || actualIndex >= thisValue.length) { + continue; + } + + let res = Array.prototype.with.call(thisValue, index, replacement); + assertEq(res.length, thisValue.length); + + for (let i = 0; i < thisValue.length; ++i) { + assertEq(Object.hasOwn(res, i), true); + + if (i === actualIndex) { + assertEq(res[i], replacement); + } else { + assertEq(res[i], thisValue[i]); + } + } + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Array/with.js b/js/src/tests/non262/Array/with.js new file mode 100644 index 0000000000..54585ebc79 --- /dev/null +++ b/js/src/tests/non262/Array/with.js @@ -0,0 +1,17 @@ +// |reftest| + +Object.defineProperty(Array.prototype, 0, { + set() { + throw "bad"; + }, +}); + +// Single element case. +assertDeepEq([0].with(0, 1), [1]); + +// More than one element. +assertDeepEq([1, 2].with(0, 3), [3, 2]); +assertDeepEq([1, 2].with(1, 3), [1, 3]); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/ArrayBuffer/CloneArrayBuffer.js b/js/src/tests/non262/ArrayBuffer/CloneArrayBuffer.js new file mode 100644 index 0000000000..480314ad8e --- /dev/null +++ b/js/src/tests/non262/ArrayBuffer/CloneArrayBuffer.js @@ -0,0 +1,35 @@ +var BUGNUMBER = 1264941; +var summary = 'CloneArrayBuffer should be called with byteLength of source typedArray'; + +print(BUGNUMBER + ": " + summary); + +function test(ctor, byteLength) { + var abuf = new ctor(byteLength); + assertEq(abuf.byteLength, byteLength); + + for (var byteOffset of [0, 16]) { + for (var elementLength = 0; + elementLength < (byteLength - byteOffset) / Float64Array.BYTES_PER_ELEMENT; + elementLength++) { + var a1 = new Float64Array(abuf, byteOffset, elementLength); + assertEq(a1.buffer.byteLength, byteLength); + assertEq(a1.byteLength, elementLength * Float64Array.BYTES_PER_ELEMENT); + assertEq(a1.byteOffset, byteOffset); + + var a2 = new Float64Array(a1); + assertEq(a2.buffer.byteLength, a1.byteLength); + assertEq(a2.byteLength, a1.byteLength); + assertEq(a2.byteOffset, 0); + } + } +} + +test(ArrayBuffer, 16); +test(ArrayBuffer, 128); + +class MyArrayBuffer extends ArrayBuffer {} +test(MyArrayBuffer, 16); +test(MyArrayBuffer, 128); + +if (typeof reportCompare === 'function') + reportCompare(true, true); diff --git a/js/src/tests/non262/ArrayBuffer/browser.js b/js/src/tests/non262/ArrayBuffer/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/ArrayBuffer/bug1689503.js b/js/src/tests/non262/ArrayBuffer/bug1689503.js new file mode 100644 index 0000000000..475ae533cc --- /dev/null +++ b/js/src/tests/non262/ArrayBuffer/bug1689503.js @@ -0,0 +1,9 @@ +// |reftest| skip-if(!xulRuntime.shell) -- needs Debugger + +let g = newGlobal({ newCompartment: true }); +let dbg = new Debugger(g); +dbg.memory.trackingAllocationSites = true; +g.createExternalArrayBuffer(64); + +if (typeof reportCompare === 'function') + reportCompare(true, true); diff --git a/js/src/tests/non262/ArrayBuffer/bug1777413.js b/js/src/tests/non262/ArrayBuffer/bug1777413.js new file mode 100644 index 0000000000..3c58aecbfc --- /dev/null +++ b/js/src/tests/non262/ArrayBuffer/bug1777413.js @@ -0,0 +1,7 @@ +// |reftest| skip-if(!xulRuntime.shell) -- needs shell functions + +var b = createExternalArrayBuffer(0); +assertEq(b.byteLength, 0); + +if (typeof reportCompare === 'function') + reportCompare(true, true); diff --git a/js/src/tests/non262/ArrayBuffer/constructorNotCallable.js b/js/src/tests/non262/ArrayBuffer/constructorNotCallable.js new file mode 100644 index 0000000000..9df97fe867 --- /dev/null +++ b/js/src/tests/non262/ArrayBuffer/constructorNotCallable.js @@ -0,0 +1,8 @@ +assertThrowsInstanceOf(() => ArrayBuffer(), TypeError); +assertThrowsInstanceOf(() => ArrayBuffer(1), TypeError); +assertThrowsInstanceOf(() => ArrayBuffer.call(null), TypeError); +assertThrowsInstanceOf(() => ArrayBuffer.apply(null, []), TypeError); +assertThrowsInstanceOf(() => Reflect.apply(ArrayBuffer, null, []), TypeError); + +if (typeof reportCompare === 'function') + reportCompare(0,0,"OK"); diff --git a/js/src/tests/non262/ArrayBuffer/getter-name.js b/js/src/tests/non262/ArrayBuffer/getter-name.js new file mode 100644 index 0000000000..434782bfe8 --- /dev/null +++ b/js/src/tests/non262/ArrayBuffer/getter-name.js @@ -0,0 +1,10 @@ +var BUGNUMBER = 1180290; +var summary = 'ArrayBuffer getters should have get prefix'; + +print(BUGNUMBER + ": " + summary); + +assertEq(Object.getOwnPropertyDescriptor(ArrayBuffer, Symbol.species).get.name, "get [Symbol.species]"); +assertEq(Object.getOwnPropertyDescriptor(ArrayBuffer.prototype, "byteLength").get.name, "get byteLength"); + +if (typeof reportCompare === 'function') + reportCompare(true, true); diff --git a/js/src/tests/non262/ArrayBuffer/shell.js b/js/src/tests/non262/ArrayBuffer/shell.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/ArrayBuffer/slice-species.js b/js/src/tests/non262/ArrayBuffer/slice-species.js new file mode 100644 index 0000000000..6f025d162c --- /dev/null +++ b/js/src/tests/non262/ArrayBuffer/slice-species.js @@ -0,0 +1,180 @@ +const tests = [ + [Int8Array, [9, 10, 11, 12, 13, 14, 15, 16]], + [Uint8Array, [9, 10, 11, 12, 13, 14, 15, 16]], + [Uint8ClampedArray, [9, 10, 11, 12, 13, 14, 15, 16]], + [Int16Array, [5, 6, 7, 8]], + [Uint16Array, [5, 6, 7, 8]], + [Int32Array, [3, 4]], + [Uint32Array, [3, 4]], + [Float32Array, [3, 4]], + [Float64Array, [2]], +]; + +let logs = []; +for (let [ctor, answer] of tests) { + let arr = new ctor([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]); + + let proxyProto = new Proxy({}, { + get(that, name) { + throw new Error("unexpected prop access"); + } + }); + + class MyArrayBuffer extends ArrayBuffer {} + + arr.buffer.constructor = new Proxy({}, { + get(that, name) { + if (name == Symbol.species) { + logs.push("get @@species"); + let C = new Proxy(function(...args) { + logs.push("call ctor"); + return new MyArrayBuffer(...args); + }, { + get(that, name) { + logs.push("get ctor." + String(name)); + if (name == "prototype") { + return proxyProto; + } + throw new Error("unexpected prop access"); + } + }); + return C; + } + throw new Error("unexpected prop access"); + } + }); + + logs.length = 0; + let buf = arr.buffer.slice(8, 16); + assertEq(buf.constructor, MyArrayBuffer); + assertDeepEq(logs, ["get @@species", "get ctor.prototype", "call ctor"]); + assertDeepEq([...new ctor(buf)], answer); + + + // modified @@species + let a = arr.buffer; + a.constructor = { + [Symbol.species]: MyArrayBuffer + }; + let b = a.slice(8, 16); + assertEq(b.constructor, MyArrayBuffer); + assertDeepEq([...new ctor(b)], answer); + + class MyArrayBufferWithSpecies extends ArrayBuffer { + get [Symbol.species]() { + return MyArrayBufferWithSpecies; + } + } + a = arr.buffer; + a.constructor = MyArrayBufferWithSpecies; + b = a.slice(8, 16); + assertEq(b.constructor, MyArrayBufferWithSpecies); + assertDeepEq([...new ctor(b)], answer); + + // no @@species + a = arr.buffer; + a.constructor = { + [Symbol.species]: undefined + }; + b = a.slice(8, 16); + assertEq(b.constructor, ArrayBuffer); + assertDeepEq([...new ctor(b)], answer); + + a = arr.buffer; + a.constructor = { + [Symbol.species]: null + }; + b = a.slice(8, 16); + assertEq(b.constructor, ArrayBuffer); + assertDeepEq([...new ctor(b)], answer); + + // invalid @@species + for (let species of [0, 1.1, true, false, "a", /a/, Symbol.iterator, [], {}]) { + a = arr.buffer; + a.constructor = { + [Symbol.species]: species + }; + assertThrowsInstanceOf(() => a.slice(8, 16), TypeError); + } + + // undefined constructor + a = arr.buffer; + a.constructor = undefined; + b = a.slice(8, 16); + assertEq(b.constructor, ArrayBuffer); + assertDeepEq([...new ctor(b)], answer); + + // invalid constructor + for (let ctor of [null, 0, 1.1, true, false, "a", Symbol.iterator]) { + a = arr.buffer; + a.constructor = ctor; + assertThrowsInstanceOf(() => a.slice(8, 16), TypeError); + } + + // @@species from different global + let g = newGlobal(); + g.eval("var MyArrayBuffer = class MyArrayBuffer extends ArrayBuffer {};"); + a = arr.buffer; + a.constructor = { + [Symbol.species]: g.MyArrayBuffer + }; + b = a.slice(8, 16); + assertEq(b.constructor, g.MyArrayBuffer); + assertDeepEq([...new ctor(b)], answer); + + a = arr.buffer; + a.constructor = { + [Symbol.species]: g.ArrayBuffer + }; + b = a.slice(8, 16); + assertEq(b.constructor, g.ArrayBuffer); + assertDeepEq([...new ctor(b)], answer); + + // constructor from different global + g.eval(` +var MyArrayBufferWithSpecies = class MyArrayBufferWithSpecies extends ArrayBuffer { + get [Symbol.species]() { + return MyArrayBufferWithSpecies; + } +}; +`); + a = arr.buffer; + a.constructor = g.MyArrayBufferWithSpecies; + b = a.slice(8, 16); + assertEq(b.constructor, g.MyArrayBufferWithSpecies); + assertDeepEq([...new ctor(b)], answer); + + g.eval(` +var arr = new ${ctor.name}([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]); +var a = arr.buffer; +`); + b = ArrayBuffer.prototype.slice.call(g.a, 8, 16); + assertEq(b.constructor, g.ArrayBuffer); + assertDeepEq([...new ctor(b)], answer); + + // running in different global + b = g.a.slice(8, 16); + assertEq(b.constructor, g.ArrayBuffer); + assertDeepEq([...new ctor(b)], answer); + + // subclasses + // not-modified @@species + a = new MyArrayBuffer(16); + b = a.slice(8, 16); + assertEq(b.constructor, MyArrayBuffer); + + // modified @@species + class MyArrayBuffer2 extends ArrayBuffer { + } + class MyArrayBuffer3 extends ArrayBuffer { + static get [Symbol.species]() { + return MyArrayBuffer2; + } + } + a = new MyArrayBuffer3(16); + b = a.slice(8, 16); + assertEq(b.constructor, MyArrayBuffer2); +} + +if (typeof reportCompare === 'function') + reportCompare(0,0,"OK"); diff --git a/js/src/tests/non262/AsyncGenerators/async-generator-declaration-in-modules.js b/js/src/tests/non262/AsyncGenerators/async-generator-declaration-in-modules.js new file mode 100644 index 0000000000..40509d990d --- /dev/null +++ b/js/src/tests/non262/AsyncGenerators/async-generator-declaration-in-modules.js @@ -0,0 +1,11 @@ +async function* f() { + return "success"; +} + +var AsyncGenerator = (async function*(){}).constructor; + +assertEq(f instanceof AsyncGenerator, true); + +f().next().then(v => { + reportCompare("success", v.value); +}); diff --git a/js/src/tests/non262/AsyncGenerators/browser.js b/js/src/tests/non262/AsyncGenerators/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/AsyncGenerators/create-function-parse-before-getprototype.js b/js/src/tests/non262/AsyncGenerators/create-function-parse-before-getprototype.js new file mode 100644 index 0000000000..1c7f8df689 --- /dev/null +++ b/js/src/tests/non262/AsyncGenerators/create-function-parse-before-getprototype.js @@ -0,0 +1,19 @@ +var getProtoCalled = false; + +var newTarget = Object.defineProperty(function(){}.bind(), "prototype", { + get() { + getProtoCalled = true; + return null; + } +}); + +var AsyncGenerator = async function*(){}.constructor; + +assertThrowsInstanceOf(() => { + Reflect.construct(AsyncGenerator, ["@error"], newTarget); +}, SyntaxError); + +assertEq(getProtoCalled, false); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/AsyncGenerators/cross-compartment.js b/js/src/tests/non262/AsyncGenerators/cross-compartment.js new file mode 100644 index 0000000000..2cf577b126 --- /dev/null +++ b/js/src/tests/non262/AsyncGenerators/cross-compartment.js @@ -0,0 +1,90 @@ +var g = newGlobal(); +g.mainGlobal = this; + +if (typeof isSameCompartment !== "function") { + var isSameCompartment = SpecialPowers.Cu.getJSTestingFunctions().isSameCompartment; +} + +var next = async function*(){}.prototype.next; + +var f = g.eval(`(async function*() { + var x = yield {message: "yield"}; + + // Input completion values are correctly wrapped into |f|'s compartment. + assertEq(isSameCompartment(x, mainGlobal), true); + assertEq(x.message, "continue"); + + return {message: "return"}; +})`); + +var it = f(); + +// The async iterator is same-compartment with |f|. +assertEq(isSameCompartment(it, f), true); + +var p1 = next.call(it, {message: "initial yield"}); + +// The promise object is same-compartment with |f|. +assertEq(isSameCompartment(p1, f), true); + +// Note: This doesn't follow the spec, which requires that only |p1 instanceof Promise| is true. +assertEq(p1 instanceof Promise || p1 instanceof g.Promise, true); + +p1.then(v => { + // The iterator result object is same-compartment with |f|. + assertEq(isSameCompartment(v, f), true); + assertEq(v.done, false); + + assertEq(isSameCompartment(v.value, f), true); + assertEq(v.value.message, "yield"); +}); + +var p2 = next.call(it, {message: "continue"}); + +// The promise object is same-compartment with |f|. +assertEq(isSameCompartment(p2, f), true); + +// Note: This doesn't follow the spec, which requires that only |p2 instanceof Promise| is true. +assertEq(p2 instanceof Promise || p2 instanceof g.Promise, true); + +p2.then(v => { + // The iterator result object is same-compartment with |f|. + assertEq(isSameCompartment(v, f), true); + assertEq(v.done, true); + + assertEq(isSameCompartment(v.value, f), true); + assertEq(v.value.message, "return"); +}); + +var p3 = next.call(it, {message: "already finished"}); + +// The promise object is same-compartment with |f|. +assertEq(isSameCompartment(p3, f), true); + +// Note: This doesn't follow the spec, which requires that only |p3 instanceof Promise| is true. +assertEq(p3 instanceof Promise || p3 instanceof g.Promise, true); + +p3.then(v => { + // The iterator result object is same-compartment with |f|. + assertEq(isSameCompartment(v, f), true); + assertEq(v.done, true); + assertEq(v.value, undefined); +}); + +var p4 = next.call({}, {message: "bad |this| argument"}); + +// The promise object is same-compartment with |next|. +assertEq(isSameCompartment(p4, next), true); + +// Only in this case we're following the spec and are creating the promise object +// in the correct realm. +assertEq(p4 instanceof Promise, true); + +p4.then(() => { + throw new Error("expected a TypeError"); +}, e => { + assertEq(e instanceof TypeError, true); +}); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncGenerators/for-await-bad-syntax.js b/js/src/tests/non262/AsyncGenerators/for-await-bad-syntax.js new file mode 100644 index 0000000000..e1d90aeb76 --- /dev/null +++ b/js/src/tests/non262/AsyncGenerators/for-await-bad-syntax.js @@ -0,0 +1,24 @@ +var AsyncGenerator = async function*(){}.constructor; + +function assertSyntaxError(code) { + var functionCode = `async function* f() { ${code} }`; + assertThrowsInstanceOf(() => AsyncGenerator(code), SyntaxError, "AsyncGenerator:" + code); + assertThrowsInstanceOf(() => eval(functionCode), SyntaxError, "eval:" + functionCode); + var ieval = eval; + assertThrowsInstanceOf(() => ieval(functionCode), SyntaxError, "indirect eval:" + functionCode); +} + +assertSyntaxError(`for await (;;) ;`); + +for (var decl of ["", "var", "let", "const"]) { + for (var head of ["a", "a = 0", "a, b", "[a]", "[a] = 0", "{a}", "{a} = 0"]) { + // Ends with C-style for loop syntax. + assertSyntaxError(`for await (${decl} ${head} ;;) ;`); + + // Ends with for-in loop syntax. + assertSyntaxError(`for await (${decl} ${head} in null) ;`); + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncGenerators/for-await-of-error.js b/js/src/tests/non262/AsyncGenerators/for-await-of-error.js new file mode 100644 index 0000000000..36e10313a4 --- /dev/null +++ b/js/src/tests/non262/AsyncGenerators/for-await-of-error.js @@ -0,0 +1,26 @@ +var BUGNUMBER = 1391519; +var summary = "for-await-of outside of async function should provide better error"; + +print(BUGNUMBER + ": " + summary); + +let caught = false; +try { + eval("for await (let x of []) {}"); +} catch(e) { + assertEq(e.message.includes("for await (... of ...) is only valid in"), true); + caught = true; +} +assertEq(caught, true); + +// Extra `await` shouldn't throw that error. +caught = false; +try { + eval("async function f() { for await await (let x of []) {} }"); +} catch(e) { + assertEq(e.message, "missing ( after for"); + caught = true; +} +assertEq(caught, true); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/AsyncGenerators/shell.js b/js/src/tests/non262/AsyncGenerators/shell.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/AsyncIterator/asynciterator.js b/js/src/tests/non262/AsyncIterator/asynciterator.js new file mode 100644 index 0000000000..048c3b4392 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/asynciterator.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) -- AsyncIterator is not enabled unconditionally +/*--- + Property descriptor of AsyncIterator. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(this, 'AsyncIterator'); +assertEq(propDesc.value, AsyncIterator); +assertEq(propDesc.writable, true); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/constructor-subclassable.js b/js/src/tests/non262/AsyncIterator/constructor-subclassable.js new file mode 100644 index 0000000000..4e8061cfe7 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/constructor-subclassable.js @@ -0,0 +1,12 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +/*--- + AsyncIterator constructor can be subclassed. +---*/ + +class TestIterator extends AsyncIterator { +} + +assertEq(new TestIterator() instanceof AsyncIterator, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/constructor-throw-when-called-directly.js b/js/src/tests/non262/AsyncIterator/constructor-throw-when-called-directly.js new file mode 100644 index 0000000000..8abc132282 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/constructor-throw-when-called-directly.js @@ -0,0 +1,9 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +/*--- + AsyncIterator constructor throws when called directly. +---*/ + +assertThrowsInstanceOf(() => new AsyncIterator(), TypeError); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/constructor-throw-without-new.js b/js/src/tests/non262/AsyncIterator/constructor-throw-without-new.js new file mode 100644 index 0000000000..699bbed007 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/constructor-throw-without-new.js @@ -0,0 +1,9 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) -- AsyncIterator is not enabled unconditionally +/*--- + AsyncIterator constructor throws when called without new. +---*/ + +assertThrowsInstanceOf(() => AsyncIterator(), TypeError); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/constructor.js b/js/src/tests/non262/AsyncIterator/constructor.js new file mode 100644 index 0000000000..e421c4e98b --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/constructor.js @@ -0,0 +1,9 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) -- AsyncIterator is not enabled unconditionally +/*--- + The AsyncIterator constructor is a built-in function. +---*/ + +assertEq(typeof AsyncIterator, 'function'); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/length.js b/js/src/tests/non262/AsyncIterator/length.js new file mode 100644 index 0000000000..26803fc44e --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/length.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) -- AsyncIterator is not enabled unconditionally +/*--- + The "length" property of AsyncIterator +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(AsyncIterator, 'length'); +assertEq(propDesc.value, 0); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/name.js b/js/src/tests/non262/AsyncIterator/name.js new file mode 100644 index 0000000000..d8944341b5 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/name.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) -- AsyncIterator is not enabled unconditionally +/*--- + The "name" property of AsyncIterator +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(AsyncIterator, 'name'); +assertEq(propDesc.value, 'AsyncIterator'); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/proto.js b/js/src/tests/non262/AsyncIterator/proto.js new file mode 100644 index 0000000000..3f19f099c7 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/proto.js @@ -0,0 +1,14 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) -- AsyncIterator is not enabled unconditionally +/*--- + The prototype of the AsyncIterator constructor is the intrinsic object %FunctionPrototype%. +---*/ + +assertEq(Object.getPrototypeOf(AsyncIterator), Function.prototype); + +const propDesc = Reflect.getOwnPropertyDescriptor(AsyncIterator, 'prototype'); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, false); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/asIndexedPairs/asIndexedPairs.js b/js/src/tests/non262/AsyncIterator/prototype/asIndexedPairs/asIndexedPairs.js new file mode 100644 index 0000000000..71ae91d602 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/asIndexedPairs/asIndexedPairs.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function* gen() { + yield 1; + yield 2; + yield 3; +} + +let iter = gen().asIndexedPairs(); + +for (const v of [[0, 1], [1, 2], [2, 3]]) { + iter.next().then( + result => { + console.log(result); + assertEq(result.done, false); + assertEq(result.value[0], v[0]); + assertEq(result.value[1], v[1]); + } + ); +} + +iter.next().then(({done}) => assertEq(done, true)); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/asIndexedPairs/length.js b/js/src/tests/non262/AsyncIterator/prototype/asIndexedPairs/length.js new file mode 100644 index 0000000000..6854cd7dd2 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/asIndexedPairs/length.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +// + +/*--- +esid: pending +description: %AsyncIterator.prototype%.asIndexedPairs length value and descriptor. +info: > + 17 ECMAScript Standard Built-in Objects +features: [iterator-helpers] +---*/ + +assertEq(AsyncIterator.prototype.asIndexedPairs.length, 0); + +const propertyDescriptor = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype.asIndexedPairs, 'length'); +assertEq(propertyDescriptor.value, 0); +assertEq(propertyDescriptor.enumerable, false); +assertEq(propertyDescriptor.writable, false); +assertEq(propertyDescriptor.configurable, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/asIndexedPairs/name.js b/js/src/tests/non262/AsyncIterator/prototype/asIndexedPairs/name.js new file mode 100644 index 0000000000..c19ac4105e --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/asIndexedPairs/name.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +/*--- +esid: pending +description: %AsyncIterator.prototype%.asIndexedPairs.name value and descriptor. +info: > + 17 ECMAScript Standard Built-in Objects +features: [iterator-helpers] +---*/ + +assertEq(AsyncIterator.prototype.asIndexedPairs.name, 'asIndexedPairs'); + +const propertyDescriptor = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype.asIndexedPairs, 'name'); +assertEq(propertyDescriptor.value, 'asIndexedPairs'); +assertEq(propertyDescriptor.enumerable, false); +assertEq(propertyDescriptor.writable, false); +assertEq(propertyDescriptor.configurable, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/async-iterator-helpers-from-other-global.js b/js/src/tests/non262/AsyncIterator/prototype/async-iterator-helpers-from-other-global.js new file mode 100644 index 0000000000..f8b8d719cd --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/async-iterator-helpers-from-other-global.js @@ -0,0 +1,65 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +class TestError extends Error {} + +class TestIterator extends AsyncIterator { + async next() { + return {done: false, value: 'value'}; + } + + closed = false; + async return(value) { + this.closed = true; + return {done: true, value}; + } +} + +function checkIterResult({done, value}, expectedDone, expectedValue) { + assertEq(done, expectedDone); + assertEq(Array.isArray(value) ? value[1] : value, expectedValue); +} + +const otherGlobal = newGlobal({newCompartment: true}); + +const methods = [ + ["map", x => x], + ["filter", x => true], + ["take", Infinity], + ["drop", 0], + ["asIndexedPairs", undefined], + ["flatMap", async function*(x) { yield x; }], +]; + +const {next: otherNext, return: otherReturn, throw: otherThrow} = + Object.getPrototypeOf(otherGlobal.eval("(async function*() {})().map(x => x)")); + +(async () => { + for (const [method, arg] of methods) { + const iterator = new TestIterator(); + const helper = iterator[method](arg); + checkIterResult(await otherNext.call(helper), false, 'value'); + } + + for (const [method, arg] of methods) { + const iterator = new TestIterator(); + const helper = iterator[method](arg); + assertEq(iterator.closed, false); + checkIterResult(await otherReturn.call(helper), true, undefined); + assertEq(iterator.closed, true); + } + + for (const [method, arg] of methods) { + const iterator = new TestIterator(); + const helper = iterator[method](arg); + try { + await otherThrow.call(helper, new TestError()); + assertEq(true, false, 'Expected exception'); + } catch (exc) { + assertEq(exc instanceof TestError, true); + } + checkIterResult(await helper.next(), true, undefined); + } +})(); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/clobber-symbol.js b/js/src/tests/non262/AsyncIterator/prototype/clobber-symbol.js new file mode 100644 index 0000000000..5db6b2276f --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/clobber-symbol.js @@ -0,0 +1,50 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +// +// + +/*--- +esid: pending +description: %AsyncIterator.prototype% methods work even if the global Symbol has been clobbered. +info: > + Iterator Helpers proposal 2.1.6 +features: [iterator-helpers, Symbol.asyncIterator] +---*/ + +Symbol = undefined; +assertThrowsInstanceOf(() => Symbol.asyncIterator, TypeError); + +async function* gen(value) { + yield value; +} + +const lazyMethods = [ + iter => iter.map(x => x), + iter => iter.filter(x => x), + iter => iter.take(1), + iter => iter.drop(0), + iter => iter.asIndexedPairs(), + iter => iter.flatMap(gen), +]; + +const strictMethods = [ + iter => iter.reduce((_, x) => x, undefined), + iter => iter.toArray(), + iter => iter.forEach(() => undefined), + iter => iter.some(x => true), + iter => iter.every(x => true), + iter => iter.find(x => true), +]; + +(async () => { + for (const method of lazyMethods) { + const {value} = await method(gen('value')).next(); + assertEq(Array.isArray(value) ? value[1] : value, 'value'); + } + + for (const method of strictMethods) { + await method(gen('value')); + } +})(); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/drop/drop-more-than-available.js b/js/src/tests/non262/AsyncIterator/prototype/drop/drop-more-than-available.js new file mode 100644 index 0000000000..45e0f91559 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/drop/drop-more-than-available.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: %AsyncIterator.prototype%.drop returns if the iterator is done. +info: > + Iterator Helpers proposal 2.1.6.5 + 1. Repeat, while remaining > 0, + ... + b. Let next be ? Await(? IteratorStep(iterated)). + c. If ? IteratorComplete(next) is true, return undefined. +features: [iterator-helpers] +---*/ + +class TestIterator extends AsyncIterator { + counter = 0; + async next() { + return {done: ++this.counter >= 2, value: undefined}; + } +} + +(async () => { + let iter = [1, 2].values().drop(3); + let result = await iter.next(); + assertEq(result.value, undefined); + assertEq(result.done, true); + + iter = new TestIterator(); + let dropped = iter.drop(10); + result = await dropped.next(); + assertEq(result.value, undefined); + assertEq(result.done, true); + assertEq(iter.counter, 2); +})(); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/drop/drop.js b/js/src/tests/non262/AsyncIterator/prototype/drop/drop.js new file mode 100644 index 0000000000..e380d7b7ed --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/drop/drop.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function* gen() { + yield 1; + yield 2; + yield 3; +} + +let iter = gen().drop(1); + +for (const v of [2, 3]) { + iter.next().then( + ({done, value}) => { + assertEq(done, false); + assertEq(value, v); + } + ); +} + +iter.next().then(({done}) => assertEq(done, true)); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/drop/length.js b/js/src/tests/non262/AsyncIterator/prototype/drop/length.js new file mode 100644 index 0000000000..6176622f17 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/drop/length.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +// + +/*--- +esid: pending +description: %AsyncIterator.prototype%.drop length value and descriptor. +info: > +features: [iterator-helpers] +---*/ + +assertEq(AsyncIterator.prototype.drop.length, 1); + +const propertyDescriptor = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype.drop, 'length'); +assertEq(propertyDescriptor.value, 1); +assertEq(propertyDescriptor.enumerable, false); +assertEq(propertyDescriptor.writable, false); +assertEq(propertyDescriptor.configurable, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/drop/name.js b/js/src/tests/non262/AsyncIterator/prototype/drop/name.js new file mode 100644 index 0000000000..ec0a73416a --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/drop/name.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +/*--- +esid: pending +description: %AsyncIterator.prototype%.drop.name value and descriptor. +info: > + 17 ECMAScript Standard Built-in Objects +features: [iterator-helpers] +---*/ + +assertEq(AsyncIterator.prototype.drop.name, 'drop'); + +const propertyDescriptor = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype.drop, 'name'); +assertEq(propertyDescriptor.value, 'drop'); +assertEq(propertyDescriptor.enumerable, false); +assertEq(propertyDescriptor.writable, false); +assertEq(propertyDescriptor.configurable, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/every/async-writes.js b/js/src/tests/non262/AsyncIterator/prototype/every/async-writes.js new file mode 100644 index 0000000000..655dfd2624 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/every/async-writes.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +let x = {a: () => true}; + +async function* gen() { + yield x.a(); + yield x.a(); +} + +gen().every(() => true).then( + () => assertEq(true, false, 'expected error'), + err => assertEq(err instanceof Error, true), +); + +x.a = () => { + throw Error(); +}; + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/every/check-fn-after-getting-iterator.js b/js/src/tests/non262/AsyncIterator/prototype/every/check-fn-after-getting-iterator.js new file mode 100644 index 0000000000..ee147ab14b --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/every/check-fn-after-getting-iterator.js @@ -0,0 +1,30 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +const log = []; +const handlerProxy = new Proxy({}, { + get: (target, key, receiver) => (...args) => { + log.push(`${key}: ${args[1]?.toString()}`); + return Reflect[key](...args); + }, +}); + +class TestIterator extends AsyncIterator { + next() { + return Promise.resolve({done: true}); + } +} + +async function* gen() { + yield 1; +} + +const iter = new Proxy(new TestIterator(), handlerProxy); +iter.every(1).then(() => assertEq(true, false, 'expected error'), err => assertEq(err instanceof TypeError, true)); + +assertEq( + log.join('\n'), + `get: every +get: next` +); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/every/coerce-result-to-boolean.js b/js/src/tests/non262/AsyncIterator/prototype/every/coerce-result-to-boolean.js new file mode 100644 index 0000000000..35c40d235e --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/every/coerce-result-to-boolean.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function* gen(value) { + yield value; +} +const fn = x => x; +function check(value, expected) { + gen(value).every(fn).then(result => assertEq(result, expected)); +} + +check(true, true); +check(1, true); +check([], true); +check({}, true); +check('test', true); + +check(false, false); +check(0, false); +check('', false); +check(null, false); +check(undefined, false); +check(NaN, false); +check(-0, false); +check(0n, false); +check(createIsHTMLDDA(), false); +check(Promise.resolve(false), false); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/every/descriptor.js b/js/src/tests/non262/AsyncIterator/prototype/every/descriptor.js new file mode 100644 index 0000000000..180085cefe --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/every/descriptor.js @@ -0,0 +1,10 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const propDesc = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype, 'every'); +assertEq(typeof propDesc.value, 'function'); +assertEq(propDesc.writable, true); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/every/error-from-correct-realm.js b/js/src/tests/non262/AsyncIterator/prototype/every/error-from-correct-realm.js new file mode 100644 index 0000000000..2ff93254ce --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/every/error-from-correct-realm.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const otherGlobal = newGlobal({newCompartment: true}); +assertEq(TypeError !== otherGlobal.TypeError, true); + +async function *gen() {} + +gen().every().then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof TypeError, true); +}); + +otherGlobal.AsyncIterator.prototype.every.call(gen()).then(() => assertEq(true, false, 'expected error'), err => { + assertEq( + err instanceof otherGlobal.TypeError, + true, + 'TypeError comes from the realm of the method.', + ); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/every/fn-not-callable-throws.js b/js/src/tests/non262/AsyncIterator/prototype/every/fn-not-callable-throws.js new file mode 100644 index 0000000000..025c46dfdf --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/every/fn-not-callable-throws.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function *gen() { + yield 1; +} + +function check(fn) { + gen().every(fn).then(() => { + throw new Error('every should have thrown'); + }, + (err) => { + assertEq(err instanceof TypeError, true); + }); +} + +check(); +check(undefined); +check(null); +check(0); +check(false); +check(''); +check(Symbol('')); +check({}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/every/fn-throws-close-iterator.js b/js/src/tests/non262/AsyncIterator/prototype/every/fn-throws-close-iterator.js new file mode 100644 index 0000000000..2a18d2ab45 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/every/fn-throws-close-iterator.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +class TestIterator extends AsyncIterator { + next() { + return Promise.resolve({ done: this.closed }); + } + + closed = false; + return() { + this.closed = true; + } +} + +const fn = () => { throw new Error(); }; +const iter = new TestIterator(); + +assertEq(iter.closed, false); +iter.every(fn).then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof Error, true); + assertEq(iter.closed, true); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/every/interleaving-calls.js b/js/src/tests/non262/AsyncIterator/prototype/every/interleaving-calls.js new file mode 100644 index 0000000000..8aacdb4316 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/every/interleaving-calls.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const log = []; +async function* gen(n) { + log.push(`${n}`); + yield 1; + log.push(`${n}`); + yield 2; +} + +Promise.all([gen(1).every(() => true), gen(2).every(() => true)]).then( + () => { + assertEq( + log.join(' '), + '1 2 1 2', + ); + }, + err => { + throw err; + } +); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/every/length.js b/js/src/tests/non262/AsyncIterator/prototype/every/length.js new file mode 100644 index 0000000000..58d7942018 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/every/length.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +/*--- + The `length` property of AsyncIterator.prototype.every. +info: | + ES7 section 17: Unless otherwise specified, the length property of a built-in + Function object has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype.every, 'length'); +assertEq(propDesc.value, 1); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/every/name.js b/js/src/tests/non262/AsyncIterator/prototype/every/name.js new file mode 100644 index 0000000000..086bfb13a6 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/every/name.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +/*--- + `name` property of AsyncIterator.prototype.every. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype.every, 'name'); +assertEq(propDesc.value, 'every'); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/every/next-throws-iterator-not-closed.js b/js/src/tests/non262/AsyncIterator/prototype/every/next-throws-iterator-not-closed.js new file mode 100644 index 0000000000..98cc850a07 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/every/next-throws-iterator-not-closed.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +class TestIterator extends AsyncIterator { + next() { + throw new Error(); + } + + closed = false; + return() { + this.closed = true; + } +} + +const fn = () => {}; +const iter = new TestIterator(); + +assertEq(iter.closed, false); +iter.every(fn).then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof Error, true); + assertEq(iter.closed, false); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/every/proxy.js b/js/src/tests/non262/AsyncIterator/prototype/every/proxy.js new file mode 100644 index 0000000000..628f143e27 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/every/proxy.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +// +// This test checks that %AsyncIterator.prototype%.every only gets the `next` method off of the +// iterator once, and never accesses the @@asyncIterator property. +const log = []; +const handlerProxy = new Proxy({}, { + get: (target, key, receiver) => (...args) => { + log.push(`${key}: ${args[1]?.toString()}`); + return Reflect[key](...args); + }, +}); + +class Counter extends AsyncIterator { + value = 0; + next() { + const value = this.value; + if (value < 2) { + this.value = value + 1; + return Promise.resolve({done: false, value}); + } + return Promise.resolve({done: true}); + } +} + +const iter = new Proxy(new Counter(), handlerProxy); +iter.every(x => x % 2 == 0).then(value => { + assertEq(value, false) + + assertEq( + log.join('\n'), + `get: every +get: next +get: value +set: value +getOwnPropertyDescriptor: value +defineProperty: value +get: value +set: value +getOwnPropertyDescriptor: value +defineProperty: value +get: return` + ); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/every/return-true-if-all-match.js b/js/src/tests/non262/AsyncIterator/prototype/every/return-true-if-all-match.js new file mode 100644 index 0000000000..01d0f75d58 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/every/return-true-if-all-match.js @@ -0,0 +1,16 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function* gen() { + yield 1; + yield 3; + yield 5; +} +const fn = x => x % 2 == 1; + +gen().every(fn).then(result => assertEq(result, true)); + +async function* empty() {} +empty().every(x => x).then(result => assertEq(result, true)); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/every/short-circuit-on-false.js b/js/src/tests/non262/AsyncIterator/prototype/every/short-circuit-on-false.js new file mode 100644 index 0000000000..7b2c74d513 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/every/short-circuit-on-false.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function* gen() { + yield 1; + yield 2; + yield 3; +} + +const log = []; +const fn = value => { + log.push(value.toString()); + return value % 2 == 1; +}; + +gen().every(fn).then(result => { + assertEq(result, false); + assertEq(log.join(','), '1,2'); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/every/this-not-iterator-throws.js b/js/src/tests/non262/AsyncIterator/prototype/every/this-not-iterator-throws.js new file mode 100644 index 0000000000..ed576c32ec --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/every/this-not-iterator-throws.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const fn = x => x; + +function check(x) { + AsyncIterator.prototype.every.call(x, fn).then( + () => { + throw new Error('check should have been rejected'); + }, + err => { + assertEq(err instanceof TypeError, true); + } + ); +} + +check(); +check(undefined); +check({}); +check({next: 0}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/every/value-throws-iterator-not-closed.js b/js/src/tests/non262/AsyncIterator/prototype/every/value-throws-iterator-not-closed.js new file mode 100644 index 0000000000..423a85ca7b --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/every/value-throws-iterator-not-closed.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +class TestError extends Error {} +class TestIterator extends AsyncIterator { + next() { + return Promise.resolve({ + done: false, + get value() { + throw new TestError(); + } + }); + } + + closed = false; + return() { + closed = true; + } +} + +const iterator = new TestIterator(); +assertEq(iterator.closed, false, 'iterator starts unclosed'); +iterator.every(x => x).then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof TestError, true); + assertEq(iterator.closed, false, 'iterator remains unclosed'); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/filter/coerce-result-to-boolean.js b/js/src/tests/non262/AsyncIterator/prototype/filter/coerce-result-to-boolean.js new file mode 100644 index 0000000000..23e3a317eb --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/filter/coerce-result-to-boolean.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function* gen(iterable) { + yield* iterable; +} + +// All truthy values are kept. +const truthyValues = [true, 1, [], {}, 'test']; +(async () => { + for await (const value of gen([...truthyValues]).filter(x => x)) { + assertEq(truthyValues.shift(), value); + } +})(); + +// All falsy values are filtered out. +const falsyValues = [false, 0, '', null, undefined, NaN, -0, 0n, createIsHTMLDDA()]; +gen(falsyValues).filter(x => x).next().then( + ({done, value}) => { + assertEq(done, true); + assertEq(value, undefined); + } +); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/filter/filter.js b/js/src/tests/non262/AsyncIterator/prototype/filter/filter.js new file mode 100644 index 0000000000..060e9853f2 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/filter/filter.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function* gen() { + yield 1; + yield 2; + yield 3; +} + +let iter = gen().filter(x => x % 2); + +for (const v of [1, 3]) { + console.log(iter); + iter.next().then( + ({done, value}) => { + assertEq(done, false); + assertEq(value, v); + } + ); +} + +iter.next().then(({done}) => assertEq(done, true)); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/filter/length.js b/js/src/tests/non262/AsyncIterator/prototype/filter/length.js new file mode 100644 index 0000000000..7ca14621ff --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/filter/length.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +// + +/*--- +esid: pending +description: %AsyncIterator.prototype%.filter length value and descriptor. +info: > + 17 ECMAScript Standard Built-in Objects +features: [iterator-helpers] +---*/ + +assertEq(AsyncIterator.prototype.filter.length, 1); + +const propertyDescriptor = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype.filter, 'length'); +assertEq(propertyDescriptor.value, 1); +assertEq(propertyDescriptor.enumerable, false); +assertEq(propertyDescriptor.writable, false); +assertEq(propertyDescriptor.configurable, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/filter/name.js b/js/src/tests/non262/AsyncIterator/prototype/filter/name.js new file mode 100644 index 0000000000..1a8e030e9a --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/filter/name.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +/*--- +esid: pending +description: %AsyncIterator.prototype%.filter.name value and descriptor. +info: > + 17 ECMAScript Standard Built-in Objects +features: [iterator-helpers] +---*/ + +assertEq(AsyncIterator.prototype.filter.name, 'filter'); + +const propertyDescriptor = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype.filter, 'name'); +assertEq(propertyDescriptor.value, 'filter'); +assertEq(propertyDescriptor.enumerable, false); +assertEq(propertyDescriptor.writable, false); +assertEq(propertyDescriptor.configurable, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/find/async-writes.js b/js/src/tests/non262/AsyncIterator/prototype/find/async-writes.js new file mode 100644 index 0000000000..6d1707e2fe --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/find/async-writes.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +let x = {a: () => true}; + +async function* gen() { + yield x.a(); + yield x.a(); +} + +gen().find(() => {}).then( + () => assertEq(true, false, 'expected error'), + err => assertEq(err instanceof Error, true), +); + +x.a = () => { + throw Error(); +}; + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/find/check-fn-after-getting-iterator.js b/js/src/tests/non262/AsyncIterator/prototype/find/check-fn-after-getting-iterator.js new file mode 100644 index 0000000000..579e4f589a --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/find/check-fn-after-getting-iterator.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +const log = []; +const handlerProxy = new Proxy({}, { + get: (target, key, receiver) => (...args) => { + log.push(`${key}: ${args[1]?.toString()}`); + return Reflect[key](...args); + }, +}); + +class TestIterator extends AsyncIterator { + next() { + return Promise.resolve({done: true}); + } +} + +const iter = new Proxy(new TestIterator(), handlerProxy); +iter.find(1).then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof TypeError, true); + assertEq( + log.join('\n'), + `get: find +get: next` + ); +}); + + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/find/coerce-result-to-boolean.js b/js/src/tests/non262/AsyncIterator/prototype/find/coerce-result-to-boolean.js new file mode 100644 index 0000000000..eb89eca840 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/find/coerce-result-to-boolean.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function* gen(value) { + yield value; +} +const fn = x => x; +function check(value, expected) { + gen(value).find(fn).then(result => assertEq(result, expected)); +} + +check(true, true); +check(1, 1); +check('test', 'test'); + +check(false, undefined); +check(0, undefined); +check('', undefined); +check(null, undefined); +check(undefined, undefined); +check(NaN, undefined); +check(-0, undefined); +check(0n, undefined); +check(Promise.resolve(false), undefined); + +let array = []; +check(array, array); + +let object = {}; +check(object, object); + +const htmlDDA = createIsHTMLDDA(); +check(htmlDDA, undefined); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/find/descriptor.js b/js/src/tests/non262/AsyncIterator/prototype/find/descriptor.js new file mode 100644 index 0000000000..7b93147d81 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/find/descriptor.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +/*--- + Descriptor property of AsyncIterator.prototype.find +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype, 'find'); +assertEq(typeof propDesc.value, 'function'); +assertEq(propDesc.writable, true); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/find/error-from-correct-realm.js b/js/src/tests/non262/AsyncIterator/prototype/find/error-from-correct-realm.js new file mode 100644 index 0000000000..37c6b4b593 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/find/error-from-correct-realm.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const otherGlobal = newGlobal({newCompartment: true}); +assertEq(TypeError !== otherGlobal.TypeError, true); + +async function *gen() {} + +gen().find().then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof TypeError, true); +}); + +otherGlobal.AsyncIterator.prototype.find.call(gen()).then(() => assertEq(true, false, 'expected error'), err => { + assertEq( + err instanceof otherGlobal.TypeError, + true, + 'TypeError comes from the realm of the method.', + ); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/find/fn-not-callable-throws.js b/js/src/tests/non262/AsyncIterator/prototype/find/fn-not-callable-throws.js new file mode 100644 index 0000000000..c858b812d3 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/find/fn-not-callable-throws.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function *gen() { + yield 1; +} + +function check(fn) { + gen().every(fn).then(() => { + throw new Error('every should have thrown'); + }, + (err) => { + assertEq(err instanceof TypeError, true); + }); +} + +check(); +check(undefined); +check(null); +check(0); +check(false); +check(''); +check(Symbol('')); +check({}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/find/fn-throws-close-iterator.js b/js/src/tests/non262/AsyncIterator/prototype/find/fn-throws-close-iterator.js new file mode 100644 index 0000000000..9544c57d4a --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/find/fn-throws-close-iterator.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +class TestIterator extends AsyncIterator { + next() { + return Promise.resolve({done: this.closed}); + } + + closed = false; + return() { + this.closed = true; + } +} + +const fn = () => { throw new Error(); }; +const iter = new TestIterator(); + +assertEq(iter.closed, false); +iter.find(fn).then(() => { + throw new Error('promise should be rejected'); +}, err => { + assertEq(err instanceof Error, true); + assertEq(iter.closed, true); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/find/interleaving-calls.js b/js/src/tests/non262/AsyncIterator/prototype/find/interleaving-calls.js new file mode 100644 index 0000000000..d973e8b030 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/find/interleaving-calls.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const log = []; +async function* gen(n) { + log.push(`${n}`); + yield 1; + log.push(`${n}`); + yield 2; +} + +Promise.all([gen(1).find(() => {}), gen(2).find(() => {})]).then( + () => { + assertEq( + log.join(' '), + '1 2 1 2', + ); + }, + err => { + throw err; + } +); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/find/length.js b/js/src/tests/non262/AsyncIterator/prototype/find/length.js new file mode 100644 index 0000000000..e207a52898 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/find/length.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +/*--- + The `length` property of AsyncIterator.prototype.find. +info: | + ES7 section 17: Unless otherwise specified, the length property of a built-in + Function object has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype.find, 'length'); +assertEq(propDesc.value, 1); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/find/name.js b/js/src/tests/non262/AsyncIterator/prototype/find/name.js new file mode 100644 index 0000000000..21e8fa90f8 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/find/name.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +/*--- + `name` property of AsyncIterator.prototype.find. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype.find, 'name'); +assertEq(propDesc.value, 'find'); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/find/next-throws-iterator-not-closed.js b/js/src/tests/non262/AsyncIterator/prototype/find/next-throws-iterator-not-closed.js new file mode 100644 index 0000000000..4c5cd3ddbd --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/find/next-throws-iterator-not-closed.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +class TestIterator extends AsyncIterator { + next() { + throw new Error(); + } + + closed = false; + return() { + this.closed = true; + } +} + +const fn = x => x; +const iter = new TestIterator(); + +assertEq(iter.closed, false); +iter.find(fn).then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof Error, true); + assertEq(iter.closed, false); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/find/proxy.js b/js/src/tests/non262/AsyncIterator/prototype/find/proxy.js new file mode 100644 index 0000000000..4f8a210b45 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/find/proxy.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +// +// This test checks that %Iterator.prototype%.find only gets the `next` method off of the +// iterator once, and never accesses the @@iterator property. +const log = []; +const handlerProxy = new Proxy({}, { + get: (target, key, receiver) => (...args) => { + log.push(`${key}: ${args[1]?.toString()}`); + return Reflect[key](...args); + }, +}); + +class Counter extends AsyncIterator { + value = 0; + next() { + const value = this.value; + if (value < 2) { + this.value = value + 1; + return Promise.resolve({done: false, value}); + } + return Promise.resolve({done: true}); + } +} + +const iter = new Proxy(new Counter(), handlerProxy); +iter.find(x => x % 2 == 1).then(value => { + assertEq(value, 1); + + assertEq( + log.join('\n'), + `get: find +get: next +get: value +set: value +getOwnPropertyDescriptor: value +defineProperty: value +get: value +set: value +getOwnPropertyDescriptor: value +defineProperty: value +get: return` + ); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/find/return-undefined-if-none-match.js b/js/src/tests/non262/AsyncIterator/prototype/find/return-undefined-if-none-match.js new file mode 100644 index 0000000000..b7dc847036 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/find/return-undefined-if-none-match.js @@ -0,0 +1,16 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function* gen() { + yield 1; + yield 3; + yield 5; +} +const fn = x => x % 2 == 0; + +gen().find(fn).then(result => assertEq(result, undefined)); + +async function* empty() {} +empty().find(x => x).then(result => assertEq(result, undefined)); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/find/short-circuit-on-match.js b/js/src/tests/non262/AsyncIterator/prototype/find/short-circuit-on-match.js new file mode 100644 index 0000000000..4404c53ac1 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/find/short-circuit-on-match.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function* gen() { + yield 1; + yield 2; + yield 3; +} + +const log = []; +const fn = (value) => { + log.push(value.toString()); + return value % 2 == 0; +}; + +gen().find(fn).then(result => { + assertEq(result, 2); + assertEq(log.join(','), '1,2'); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/find/this-not-iterator-throws.js b/js/src/tests/non262/AsyncIterator/prototype/find/this-not-iterator-throws.js new file mode 100644 index 0000000000..97c8b142a2 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/find/this-not-iterator-throws.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const fn = x => x; + +function check(x) { + AsyncIterator.prototype.find.call(x, fn).then( + () => assertEq(true, false, 'expected error'), + err => { + assertEq(err instanceof TypeError, true); + } + ); +} + +check(); +check(undefined); +check({}); +check({next: 0}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/find/value-throws-iterator-not-closed.js b/js/src/tests/non262/AsyncIterator/prototype/find/value-throws-iterator-not-closed.js new file mode 100644 index 0000000000..c639eea5a4 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/find/value-throws-iterator-not-closed.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +class TestError extends Error {} +class TestIterator extends AsyncIterator { + next() { + return Promise.resolve({ + done: false, + get value() { + throw new TestError(); + } + }); + } + + closed = false; + return() { + closed = true; + } +} + +const iterator = new TestIterator(); +assertEq(iterator.closed, false, 'iterator starts unclosed'); +iterator.find(x => x).then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof TestError, true); + assertEq(iterator.closed, false, 'iterator remains unclosed'); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/flatMap/close-iterator-when-inner-complete-throws.js b/js/src/tests/non262/AsyncIterator/prototype/flatMap/close-iterator-when-inner-complete-throws.js new file mode 100644 index 0000000000..bca8f7c316 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/flatMap/close-iterator-when-inner-complete-throws.js @@ -0,0 +1,55 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: %AsyncIterator.prototype%.flatMap closes the iterator when innerComplete throws. +info: > + Iterator Helpers proposal 2.1.6.7 + 1. Repeat, + ... + k. Repeat, while innerAlive is true, + ... + v. Let innerComplete be IteratorComplete(innerNext). + vi. IfAbruptCloseAsyncIterator(innerComplete, iterated). +features: [iterator-helpers] +---*/ + +class TestIterator extends AsyncIterator { + async next() { + return {done: false, value: 0}; + } + + closed = false; + async return() { + this.closed = true; + return {done: true}; + } +} + +class TestError extends Error {} +class InnerIterator extends AsyncIterator { + async next() { + return { + get done() { + throw new TestError(); + } + }; + } +} + +const iter = new TestIterator(); +const mapped = iter.flatMap(x => new InnerIterator()); + +assertEq(iter.closed, false); +mapped.next().then( + _ => assertEq(true, false, 'Expected reject.'), + err => { + assertEq(err instanceof TestError, true); + assertEq(iter.closed, true); + } +); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/flatMap/close-iterator-when-inner-next-throws.js b/js/src/tests/non262/AsyncIterator/prototype/flatMap/close-iterator-when-inner-next-throws.js new file mode 100644 index 0000000000..d92732e9fd --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/flatMap/close-iterator-when-inner-next-throws.js @@ -0,0 +1,50 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: %AsyncIterator.prototype%.flatMap closes the iterator when IteratorNext throws. +info: > + Iterator Helpers proposal 2.1.6.7 + 1. Repeat, + ... + k. Repeat, while innerAlive is true, + i. Let innerNextPromise be IteratorNext(innerIterator). + ii. IfAbruptCloseAsyncIterator(innerNextPromise, iterated). +features: [iterator-helpers] +---*/ + +class TestIterator extends AsyncIterator { + async next() { + return {done: false, value: 0}; + } + + closed = false; + async return(value) { + this.closed = true; + return {done: true, value}; + } +} + +class TestError extends Error {} +class InnerIterator extends AsyncIterator { + async next() { + throw new TestError(); + } +} + +const iter = new TestIterator(); +const mapped = iter.flatMap(x => new InnerIterator()); + +assertEq(iter.closed, false); +mapped.next().then( + _ => assertEq(true, false, 'Expected reject.'), + err => { + assertEq(err instanceof TestError, true); + assertEq(iter.closed, true); + } +); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/flatMap/close-iterator-when-inner-value-throws.js b/js/src/tests/non262/AsyncIterator/prototype/flatMap/close-iterator-when-inner-value-throws.js new file mode 100644 index 0000000000..97a82ec0bb --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/flatMap/close-iterator-when-inner-value-throws.js @@ -0,0 +1,57 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: %AsyncIterator.prototype%.flatMap closes the iterator when innerValue throws. +info: > + Iterator Helpers proposal 2.1.6.7 + 1. Repeat, + ... + k. Repeat, while innerAlive is true, + ... + viii. Else, + 1. Let innerValue be IteratorValue(innerNext). + 2. IfAbruptCloseAsyncIterator(innerValue, iterated). +features: [iterator-helpers] +---*/ + +class TestIterator extends AsyncIterator { + async next() { + return {done: false, value: 0}; + } + + closed = false; + async return() { + this.closed = true; + return {done: true}; + } +} + +class TestError extends Error {} +class InnerIterator extends AsyncIterator { + async next() { + return { + done: false, + get value() { + throw new TestError(); + }, + }; + } +} + +const iter = new TestIterator(); +const mapped = iter.flatMap(x => new InnerIterator()); + +assertEq(iter.closed, false); +mapped.next().then( + _ => assertEq(true, false, 'Expected reject.'), + err => { + assertEq(err instanceof TestError, true); + assertEq(iter.closed, true); + } +); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/flatMap/flatMap.js b/js/src/tests/non262/AsyncIterator/prototype/flatMap/flatMap.js new file mode 100644 index 0000000000..dbd17cb33b --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/flatMap/flatMap.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function* gen() { + yield 1; + yield 2; + yield 3; +} + +async function* inner(x) { + yield x; + yield x + 1; +} + +let iter = gen().flatMap(x => inner(x)); + +for (const v of [1, 2, 2, 3, 3, 4]) { + iter.next().then( + ({done, value}) => { + assertEq(done, false); + assertEq(value, v); + } + ); +} + +iter.next().then(({done}) => assertEq(done, true)); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/flatMap/inner-empty-iterable.js b/js/src/tests/non262/AsyncIterator/prototype/flatMap/inner-empty-iterable.js new file mode 100644 index 0000000000..3da588f444 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/flatMap/inner-empty-iterable.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: %AsyncIterator.prototype%.flatMap skips empty inner iterables. +info: > + Iterator Helpers proposal 2.1.6.7 + 1. Repeat, + ... + k. Repeat, while innerAlive is true, + ... + v. Let innerComplete be IteratorComplete(innerNext). + ... + vii. If innerComplete is true, set innerAlive to false. +features: [iterator-helpers] +---*/ + +async function* gen(values) { + yield* values; +} + +(async () => { + let iter = gen([0, 1, 2, 3]).flatMap(x => x % 2 ? gen([]) : gen([x])); + + for (const expected of [0, 2]) { + const result = await iter.next(); + assertEq(result.value, expected); + assertEq(result.done, false); + } + + let result = await iter.next(); + assertEq(result.value, undefined); + assertEq(result.done, true); + + iter = gen([0, 1, 2, 3]).flatMap(x => gen([])); + result = await iter.next(); + assertEq(result.value, undefined); + assertEq(result.done, true); +})(); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/flatMap/inner-generator.js b/js/src/tests/non262/AsyncIterator/prototype/flatMap/inner-generator.js new file mode 100644 index 0000000000..08c0dfbba7 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/flatMap/inner-generator.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: %AsyncIterator.prototype%.flatMap innerIterator can be a generator. +info: > + Iterator Helpers proposal 2.1.6.7 +features: [iterator-helpers] +---*/ + +async function* gen() { + yield 1; + yield 2; +} + +(async () => { + const iter = gen().flatMap(async function*(x) { + yield x; + yield* [x + 1, x + 2]; + }); + + for (const expected of [1, 2, 3, 2, 3, 4]) { + const result = await iter.next(); + assertEq(result.value, expected); + assertEq(result.done, false); + } + + const result = await iter.next(); + assertEq(result.value, undefined); + assertEq(result.done, true); +})(); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/flatMap/length.js b/js/src/tests/non262/AsyncIterator/prototype/flatMap/length.js new file mode 100644 index 0000000000..4e6862cd41 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/flatMap/length.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +// + +/*--- +esid: pending +description: %AsyncIterator.prototype%.flatMap length value and descriptor. +info: > + 17 ECMAScript Standard Built-in Objects +features: [iterator-helpers] +---*/ + +assertEq(AsyncIterator.prototype.flatMap.length, 1); + +const propertyDescriptor = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype.flatMap, 'length'); +assertEq(propertyDescriptor.value, 1); +assertEq(propertyDescriptor.enumerable, false); +assertEq(propertyDescriptor.writable, false); +assertEq(propertyDescriptor.configurable, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/flatMap/name.js b/js/src/tests/non262/AsyncIterator/prototype/flatMap/name.js new file mode 100644 index 0000000000..2aeebe0f85 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/flatMap/name.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +/*--- +esid: pending +description: %AsyncIterator.prototype%.flatMap.name value and descriptor. +info: > + 17 ECMAScript Standard Built-in Objects +features: [iterator-helpers] +---*/ + +assertEq(AsyncIterator.prototype.flatMap.name, 'flatMap'); + +const propertyDescriptor = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype.flatMap, 'name'); +assertEq(propertyDescriptor.value, 'flatMap'); +assertEq(propertyDescriptor.enumerable, false); +assertEq(propertyDescriptor.writable, false); +assertEq(propertyDescriptor.configurable, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/flatMap/throw-when-inner-not-iterable.js b/js/src/tests/non262/AsyncIterator/prototype/flatMap/throw-when-inner-not-iterable.js new file mode 100644 index 0000000000..e854a8c8ae --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/flatMap/throw-when-inner-not-iterable.js @@ -0,0 +1,71 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: %AsyncIterator.prototype%.flatMap closes the iterator and throws when mapped isn't iterable. +info: > + Iterator Helpers proposal 2.1.6.7 + 1. Repeat, + ... + h. Let innerIterator be GetIterator(mapped, async). + i. IfAbruptCloseAsyncIterator(innerIterator, iterated). +features: [iterator-helpers] +---*/ + +class NotIterable { + async next() { + return {done: true}; + } +} + +class InvalidIterable { + [Symbol.asyncIterator]() { + return {}; + } +} + +class TestIterator extends AsyncIterator { + async next() { + return {done: false, value: 0}; + } + + closed = false; + async return(value) { + this.closed = true; + return {done: true, value}; + } +} + +const nonIterables = [ + new NotIterable(), + new InvalidIterable(), + undefined, + null, + 0, + false, + Symbol(''), + 0n, + {}, +]; + +(async () => { + for (const value of nonIterables) { + const iter = new TestIterator(); + const mapped = iter.flatMap(x => value); + + assertEq(iter.closed, false); + console.log("here!"); + try { + await mapped.next(); + assertEq(true, false, 'Expected reject'); + } catch (exc) { + assertEq(exc instanceof TypeError, true); + } + assertEq(iter.closed, true); + } +})(); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/forEach/async-writes.js b/js/src/tests/non262/AsyncIterator/prototype/forEach/async-writes.js new file mode 100644 index 0000000000..25c4302ade --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/forEach/async-writes.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +let x = {a: () => true}; + +async function* gen() { + yield x.a(); + yield x.a(); +} + +gen().forEach(() => {}).then( + () => assertEq(true, false, 'expected error'), + err => assertEq(err instanceof Error, true), +); + +x.a = () => { + throw Error(); +}; + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/forEach/check-fn-after-getting-iterator.js b/js/src/tests/non262/AsyncIterator/prototype/forEach/check-fn-after-getting-iterator.js new file mode 100644 index 0000000000..bcf77e56d1 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/forEach/check-fn-after-getting-iterator.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +const log = []; +const handlerProxy = new Proxy({}, { + get: (target, key, receiver) => (...args) => { + log.push(`${key}: ${args[1]?.toString()}`); + return Reflect[key](...args); + }, +}); + +class TestIterator extends AsyncIterator { + next() { + return Promise.resolve({done: true}); + } +} + +const iter = new Proxy(new TestIterator(), handlerProxy); +iter.forEach(1).then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof TypeError, true); + assertEq( + log.join('\n'), + `get: forEach +get: next` + ); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/forEach/descriptor.js b/js/src/tests/non262/AsyncIterator/prototype/forEach/descriptor.js new file mode 100644 index 0000000000..8825422a28 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/forEach/descriptor.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +/*--- + Descriptor property of AsyncIterator.prototype.forEach +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype, 'forEach'); +assertEq(typeof propDesc.value, 'function'); +assertEq(propDesc.writable, true); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/forEach/error-from-correct-realm.js b/js/src/tests/non262/AsyncIterator/prototype/forEach/error-from-correct-realm.js new file mode 100644 index 0000000000..32797fe750 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/forEach/error-from-correct-realm.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const otherGlobal = newGlobal({newCompartment: true}); +assertEq(TypeError !== otherGlobal.TypeError, true); + +async function *gen() {} + +gen().forEach().then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof TypeError, true); +}); + +otherGlobal.AsyncIterator.prototype.forEach.call(gen()).then(() => assertEq(true, false, 'expected error'), err => { + assertEq( + err instanceof otherGlobal.TypeError, + true, + 'TypeError comes from the realm of the method.', + ); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/forEach/fn-not-callable-throws.js b/js/src/tests/non262/AsyncIterator/prototype/forEach/fn-not-callable-throws.js new file mode 100644 index 0000000000..c70e336bff --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/forEach/fn-not-callable-throws.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function *gen() {} + +function check(fn) { + gen().forEach(fn).then(() => { + throw new Error('every should have thrown'); + }, + (err) => { + assertEq(err instanceof TypeError, true); + }); +} + +check(); +check(undefined); +check(null); +check(0); +check(false); +check(''); +check(Symbol('')); +check({}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/forEach/fn-throws-close-iterator.js b/js/src/tests/non262/AsyncIterator/prototype/forEach/fn-throws-close-iterator.js new file mode 100644 index 0000000000..4e7d60412e --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/forEach/fn-throws-close-iterator.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +class TestIterator extends AsyncIterator { + next() { + return Promise.resolve({ done: this.closed }); + } + + closed = false; + return() { + this.closed = true; + } +} + +const fn = () => { throw new Error(); }; +const iter = new TestIterator(); + +assertEq(iter.closed, false); +iter.forEach(fn).then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof Error, true); + assertEq(iter.closed, true); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/forEach/forEach.js b/js/src/tests/non262/AsyncIterator/prototype/forEach/forEach.js new file mode 100644 index 0000000000..2109be5fd6 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/forEach/forEach.js @@ -0,0 +1,11 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const log = []; +const fn = (value) => log.push(value); +const iter = [1, 2, 3].values(); + +assertEq(iter.forEach(fn), undefined); +assertEq(log.join(','), '1,2,3'); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/forEach/interleaving-calls.js b/js/src/tests/non262/AsyncIterator/prototype/forEach/interleaving-calls.js new file mode 100644 index 0000000000..c8c47bde45 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/forEach/interleaving-calls.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const log = []; +async function* gen(n) { + log.push(`${n}`); + yield 1; + log.push(`${n}`); + yield 2; +} + +Promise.all([gen(1).forEach(() => {}), gen(2).forEach(() => {})]).then( + () => { + assertEq( + log.join(' '), + '1 2 1 2', + ); + }, + err => { + throw err; + } +); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/forEach/length.js b/js/src/tests/non262/AsyncIterator/prototype/forEach/length.js new file mode 100644 index 0000000000..5e59af9fea --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/forEach/length.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +/*--- + The `length` property of AsyncIterator.prototype.forEach. +info: | + ES7 section 17: Unless otherwise specified, the length property of a built-in + Function object has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype.forEach, 'length'); +assertEq(propDesc.value, 1); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/forEach/name.js b/js/src/tests/non262/AsyncIterator/prototype/forEach/name.js new file mode 100644 index 0000000000..3053c3967f --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/forEach/name.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +/*--- + `name` property of AsyncIterator.prototype.forEach. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype.forEach, 'name'); +assertEq(propDesc.value, 'forEach'); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/forEach/next-throws-iterator-not-closed.js b/js/src/tests/non262/AsyncIterator/prototype/forEach/next-throws-iterator-not-closed.js new file mode 100644 index 0000000000..0c72c700e2 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/forEach/next-throws-iterator-not-closed.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +class TestIterator extends AsyncIterator { + next() { + throw new Error(); + } + + closed = false; + return() { + this.closed = true; + } +} + +const fn = () => {}; +const iter = new TestIterator(); + +assertEq(iter.closed, false); +iter.forEach(fn).then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof Error, true); + assertEq(iter.closed, false); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/forEach/proxy.js b/js/src/tests/non262/AsyncIterator/prototype/forEach/proxy.js new file mode 100644 index 0000000000..bab7a2e864 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/forEach/proxy.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +// +// This test checks that %Iterator.prototype%.forEach only gets the `next` method off of the +// iterator once, and never accesses the @@iterator property. +const log = []; +const handlerProxy = new Proxy({}, { + get: (target, key, receiver) => (...args) => { + log.push(`${key}: ${args[1]?.toString()}`); + return Reflect[key](...args); + }, +}); + +class Counter extends AsyncIterator { + value = 0; + next() { + const value = this.value; + if (value < 2) { + this.value = value + 1; + return Promise.resolve({done: false, value}); + } + return Promise.resolve({done: true}); + } +} + +const iter = new Proxy(new Counter(), handlerProxy); +iter.forEach(x => x).then(() => { + assertEq( + log.join('\n'), + `get: forEach +get: next +get: value +set: value +getOwnPropertyDescriptor: value +defineProperty: value +get: value +set: value +getOwnPropertyDescriptor: value +defineProperty: value +get: value` + ); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/forEach/this-not-iterator-throws.js b/js/src/tests/non262/AsyncIterator/prototype/forEach/this-not-iterator-throws.js new file mode 100644 index 0000000000..c92536fbe6 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/forEach/this-not-iterator-throws.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const fn = x => x; +function check(x) { + AsyncIterator.prototype.forEach.call(x, fn).then( + () => assertEq(true, false, 'expected error'), + err => { + assertEq(err instanceof TypeError, true); + } + ); +} + +check(); +check(undefined); +check({}); +check({next: 0}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/forEach/value-throws-iterator-not-closed.js b/js/src/tests/non262/AsyncIterator/prototype/forEach/value-throws-iterator-not-closed.js new file mode 100644 index 0000000000..8611a0100f --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/forEach/value-throws-iterator-not-closed.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +class TestError extends Error {} +class TestIterator extends AsyncIterator { + next() { + return Promise.resolve({ + done: false, + get value() { + throw new TestError(); + } + }); + } + + closed = false; + return() { + closed = true; + } +} + +const iterator = new TestIterator(); +assertEq(iterator.closed, false, 'iterator starts unclosed'); +iterator.forEach(x => x).then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof TestError, true); + assertEq(iterator.closed, false, 'iterator remains unclosed'); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/generator-methods-throw-on-iterator-helpers.js b/js/src/tests/non262/AsyncIterator/prototype/generator-methods-throw-on-iterator-helpers.js new file mode 100644 index 0000000000..0e5b6ac0b5 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/generator-methods-throw-on-iterator-helpers.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const asyncGeneratorProto = Object.getPrototypeOf( + Object.getPrototypeOf( + (async function *() {})() + ) +); + +const methods = [ + iter => iter.map(x => x), + iter => iter.filter(x => x), + iter => iter.take(1), + iter => iter.drop(0), + iter => iter.asIndexedPairs(), + iter => iter.flatMap(x => (async function*() {})()), +]; + +for (const method of methods) { + const iteratorHelper = method((async function*() {})()); + asyncGeneratorProto.next.call(iteratorHelper).then( + _ => assertEq(true, false, 'Expected reject'), + err => assertEq(err instanceof TypeError, true), + ); + asyncGeneratorProto.return.call(iteratorHelper).then( + _ => assertEq(true, false, 'Expected reject'), + err => assertEq(err instanceof TypeError, true), + ); + asyncGeneratorProto.throw.call(iteratorHelper).then( + _ => assertEq(true, false, 'Expected reject'), + err => assertEq(err instanceof TypeError, true), + ); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/iterator-helper-methods-throw-on-generators.js b/js/src/tests/non262/AsyncIterator/prototype/iterator-helper-methods-throw-on-generators.js new file mode 100644 index 0000000000..f79fb7d842 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/iterator-helper-methods-throw-on-generators.js @@ -0,0 +1,12 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function *gen() { yield 'value'; } + +const asyncIteratorHelperProto = Object.getPrototypeOf(gen().map(x => x)); + +assertThrowsInstanceOf(() => asyncIteratorHelperProto.next.call(gen()), TypeError); +assertThrowsInstanceOf(() => asyncIteratorHelperProto.return.call(gen()), TypeError); +assertThrowsInstanceOf(() => asyncIteratorHelperProto.throw.call(gen()), TypeError); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-from-other-global.js b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-from-other-global.js new file mode 100644 index 0000000000..8b7a945fd5 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-from-other-global.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function* gen(values) { + yield* values; +} + +const otherAsyncIteratorProto = newGlobal({newCompartment: true}).AsyncIterator.prototype; + +const methods = [ + ["map", x => x], + ["filter", x => true], + ["take", Infinity], + ["drop", 0], + ["asIndexedPairs", undefined], + ["flatMap", x => gen([x])], +]; + +(async () => { + for (const [method, arg] of methods) { + const iterator = gen([1, 2, 3]); + const helper = otherAsyncIteratorProto[method].call(iterator, arg); + + for (const expected of [1, 2, 3]) { + const {done, value} = await helper.next(); + assertEq(done, false); + assertEq(Array.isArray(value) ? value[1] : value, expected); + } + + const {done, value} = await helper.next(); + assertEq(done, true); + assertEq(value, undefined); + } +})(); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-handle-empty-iterators.js b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-handle-empty-iterators.js new file mode 100644 index 0000000000..b1bd426dd8 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-handle-empty-iterators.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: Lazy %AsyncIterator.prototype% methods handle empty iterators. +info: > + Iterator Helpers proposal 2.1.6 +features: [iterator-helpers] +---*/ + +class EmptyIterator extends AsyncIterator { + async next() { + return {done: true}; + } +} + +async function* gen() {} + +const methods = [ + iter => iter.map(x => x), + iter => iter.filter(x => x), + iter => iter.take(1), + iter => iter.drop(0), + iter => iter.asIndexedPairs(), + iter => iter.flatMap(x => gen()), +]; + +for (const method of methods) { + for (const iterator of [new EmptyIterator(), gen()]) { + method(iterator).next().then( + ({done, value}) => { + assertEq(done, true); + assertEq(value, undefined); + } + ); + } +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-interleaved.js b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-interleaved.js new file mode 100644 index 0000000000..98c2a2b680 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-interleaved.js @@ -0,0 +1,59 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: Lazy %AsyncIterator.prototype% method calls can be interleaved. +info: > + Iterator Helpers proposal 2.1.6 +features: [iterator-helpers] +---*/ + +class TestIterator extends AsyncIterator { + value = 0; + async next() { + return {done: false, value: this.value++}; + } +} + +function unwrapResult(value) { + // Unwrap the asIndexedPair return values. + while (Array.isArray(value)) { + value = value[1]; + } + return value; +} + +function check({done, value}, expectedDone, expectedValue) { + assertEq(done, expectedDone); + assertEq(unwrapResult(value), expectedValue); +} + +const methods = [ + ['map', x => x], + ['filter', x => true], + ['take', Infinity], + ['drop', 0], + ['asIndexedPairs', undefined], + ['flatMap', async function*(x) { yield x; }], +]; + +(async () => { + for (const [firstMethod, firstArg] of methods) { + for (const [secondMethod, secondArg] of methods) { + const iterator = new TestIterator(); + + const firstHelper = iterator[firstMethod](firstArg); + const secondHelper = iterator[secondMethod](secondArg); + + check(await firstHelper.next(), false, 0); + check(await secondHelper.next(), false, 1); + check(await firstHelper.next(), false, 2); + check(await secondHelper.next(), false, 3); + } + } +})(); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-closed-on-call-throws.js b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-closed-on-call-throws.js new file mode 100644 index 0000000000..1a52d113f9 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-closed-on-call-throws.js @@ -0,0 +1,49 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: Lazy %AsyncIterator.prototype% methods close the iterator if callback throws. +info: > + AsyncIterator Helpers proposal 2.1.6 +features: [iterator-helpers] +---*/ + +class TestError extends Error {} +class TestAsyncIterator extends AsyncIterator { + async next() { + return {done: false, value: 1}; + } + + closed = false; + async return() { + this.closed = true; + return {done: true}; + } +} + +function fn() { + throw new TestError(); +} +const methods = [ + iter => iter.map(fn), + iter => iter.filter(fn), + iter => iter.flatMap(fn), +]; + +for (const method of methods) { + const iter = new TestAsyncIterator(); + assertEq(iter.closed, false); + method(iter).next().then( + _ => assertEq(true, false, 'Expected reject'), + err => { + assertEq(err instanceof TestError, true); + assertEq(iter.closed, true); + }, + ); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); + diff --git a/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-closed-on-yield-throws.js b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-closed-on-yield-throws.js new file mode 100644 index 0000000000..bec857eb33 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-closed-on-yield-throws.js @@ -0,0 +1,53 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: Lazy %AsyncIterator.prototype% methods close the iterator if `yield` throws. +info: > + AsyncIterator Helpers proposal 2.1.6 +features: [iterator-helpers] +---*/ + +class TestError extends Error {} +class TestAsyncIterator extends AsyncIterator { + async next() { + return {done: false, value: 1}; + } + + closed = false; + async return(value) { + this.closed = true; + return {done: true, value}; + } +} + +async function* gen(x) { yield x; } +const methods = [ + iter => iter.map(x => x), + iter => iter.filter(x => true), + iter => iter.take(1), + iter => iter.drop(0), + iter => iter.asIndexedPairs(), + iter => iter.flatMap(gen), +]; + +for (const method of methods) { + const iterator = new TestAsyncIterator(); + const iteratorHelper = method(iterator); + + assertEq(iterator.closed, false); + iteratorHelper.next().then( + _ => iteratorHelper.throw(new TestError()).then( + _ => assertEq(true, false, 'Expected reject'), + err => { + assertEq(err instanceof TestError, true); + assertEq(iterator.closed, true); + }, + ), + ); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-not-closed-on-next-get-then-throws.js b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-not-closed-on-next-get-then-throws.js new file mode 100644 index 0000000000..a9c8a6ebca --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-not-closed-on-next-get-then-throws.js @@ -0,0 +1,57 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: Lazy %AsyncIterator.prototype% methods don't close the iterator if getting `then` throws. +info: > + AsyncIterator Helpers proposal 2.1.6 +features: [iterator-helpers] +---*/ + +class TestError extends Error {} + +class TestIterator extends AsyncIterator { + next() { + return { + get then() { + throw new TestError(); + } + }; + } + + closed = false; + async return(value) { + this.closed = true; + return {done: true, value}; + } +} + +const methods = [ + ["map", x => x], + ["filter", x => true], + ["take", Infinity], + ["drop", 0], + ["asIndexedPairs", undefined], + ["flatMap", async function*(x) { yield x; }], +]; + +(async () => { + for (const [method, arg] of methods) { + const iterator = new TestIterator(); + assertEq(iterator.closed, false); + + try { + await iterator[method](arg).next(); + assertEq(true, false, 'Expected exception'); + } catch(err) { + console.log(err); + assertEq(err instanceof TestError, true); + } + assertEq(iterator.closed, false); + } +})(); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-not-closed-on-next-promise-executor-throws.js b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-not-closed-on-next-promise-executor-throws.js new file mode 100644 index 0000000000..838c381b17 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-not-closed-on-next-promise-executor-throws.js @@ -0,0 +1,53 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: Lazy %AsyncIterator.prototype% methods don't close the iterator if executor of Promise returned by `.next` throws. +info: > + AsyncIterator Helpers proposal 2.1.6 +features: [iterator-helpers] +---*/ + +class TestError extends Error {} +class TestIterator extends AsyncIterator { + next() { + return new Promise((resolve, reject) => { + throw new TestError(); + }); + } + + closed = false; + async return(value) { + this.closed = true; + return {done: true, value}; + } +} + +const methods = [ + ["map", x => x], + ["filter", x => true], + ["take", Infinity], + ["drop", 0], + ["asIndexedPairs", undefined], + ["flatMap", async function*(x) { yield x; }], +]; + +(async () => { + for (const [method, arg] of methods) { + const iterator = new TestIterator(); + assertEq(iterator.closed, false); + + try { + await iterator[method](arg).next(); + assertEq(true, false, 'Expected exception'); + } catch(err) { + assertEq(err instanceof TestError, true); + } + assertEq(iterator.closed, false); + } +})(); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-not-closed-on-next-returns-reject.js b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-not-closed-on-next-returns-reject.js new file mode 100644 index 0000000000..65eede2a6b --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-not-closed-on-next-returns-reject.js @@ -0,0 +1,51 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: Lazy %AsyncIterator.prototype% methods don't close the iterator if `.next` returns a rejected Promise. +info: > + AsyncIterator Helpers proposal 2.1.6 +features: [iterator-helpers] +---*/ + +class TestError extends Error {} +class TestIterator extends AsyncIterator { + next() { + return Promise.reject(new TestError()); + } + + closed = false; + async return(value) { + this.closed = true; + return {done: true, value}; + } +} + +const methods = [ + ["map", x => x], + ["filter", x => true], + ["take", Infinity], + ["drop", 0], + ["asIndexedPairs", undefined], + ["flatMap", async function*(x) { yield x; }], +]; + +(async () => { + for (const [method, arg] of methods) { + const iterator = new TestIterator(); + assertEq(iterator.closed, false); + + try { + await iterator[method](arg).next(); + assertEq(true, false, 'Expected exception'); + } catch(err) { + assertEq(err instanceof TestError, true); + } + assertEq(iterator.closed, false); + } +})(); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-not-closed-on-next-then-throws.js b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-not-closed-on-next-then-throws.js new file mode 100644 index 0000000000..609a49c3c7 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-not-closed-on-next-then-throws.js @@ -0,0 +1,57 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: Lazy %AsyncIterator.prototype% methods don't close the iterator if `then` returned by `next` throws. +info: > + AsyncIterator Helpers proposal 2.1.6 +features: [iterator-helpers] +---*/ + +class TestError extends Error {} + +class TestIterator extends AsyncIterator { + next() { + return { + then() { + throw new TestError(); + } + }; + } + + closed = false; + async return(value) { + this.closed = true; + return {done: true, value}; + } +} + +const methods = [ + ["map", x => x], + ["filter", x => true], + ["take", Infinity], + ["drop", 0], + ["asIndexedPairs", undefined], + ["flatMap", async function*(x) { yield x; }], +]; + +(async () => { + for (const [method, arg] of methods) { + const iterator = new TestIterator(); + assertEq(iterator.closed, false); + + try { + await iterator[method](arg).next(); + assertEq(true, false, 'Expected exception'); + } catch(err) { + console.log(err); + assertEq(err instanceof TestError, true); + } + assertEq(iterator.closed, false); + } +})(); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-not-closed-on-next-throws.js b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-not-closed-on-next-throws.js new file mode 100644 index 0000000000..ff42a3f7b6 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-not-closed-on-next-throws.js @@ -0,0 +1,49 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: Lazy %AsyncIterator.prototype% methods don't close the iterator if `.next` call throws. +info: > + AsyncIterator Helpers proposal 2.1.6 +features: [iterator-helpers] +---*/ + +class TestError extends Error {} +class TestAsyncIterator extends AsyncIterator { + next() { + throw new TestError(); + } + + closed = false; + async return(value) { + this.closed = true; + return {done: true, value}; + } +} + +async function* gen(x) { yield x; } +const methods = [ + iter => iter.map(x => x), + iter => iter.filter(x => x), + iter => iter.take(1), + iter => iter.drop(0), + iter => iter.asIndexedPairs(), + iter => iter.flatMap(gen), +]; + +for (const method of methods) { + const iterator = new TestAsyncIterator(); + assertEq(iterator.closed, false); + method(iterator).next().then( + _ => assertEq(true, false, 'Expected reject'), + err => { + assertEq(err instanceof TestError, true); + assertEq(iterator.closed, false); + }, + ); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-not-closed-on-value-throws.js b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-not-closed-on-value-throws.js new file mode 100644 index 0000000000..1578070553 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-not-closed-on-value-throws.js @@ -0,0 +1,54 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: Lazy %AsyncIterator.prototype% methods don't close the iterator if `value` throws. +info: > + AsyncIterator Helpers proposal 2.1.6 +features: [iterator-helpers] +---*/ + +class TestError extends Error {} +class TestAsyncIterator extends AsyncIterator { + async next() { + return { + get value() { + throw new TestError(); + } + }; + } + + closed = false; + async return(value) { + this.closed = true; + return {done: true, value}; + } +} + +const iterator = new TestAsyncIterator(); + +async function* gen(x) { yield x; } +const methods = [ + iter => iter.map(x => x), + iter => iter.filter(x => x), + iter => iter.take(1), + iter => iter.drop(0), + iter => iter.asIndexedPairs(), + iter => iter.flatMap(gen), +]; + +for (const method of methods) { + assertEq(iterator.closed, false); + method(iterator).next().then( + _ => assertEq(true, false, 'Expected reject'), + err => { + assertEq(err instanceof TestError, true); + assertEq(iterator.closed, false); + }, + ); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-returns-done-generator-finishes.js b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-returns-done-generator-finishes.js new file mode 100644 index 0000000000..d7e2be8f5d --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-iterator-returns-done-generator-finishes.js @@ -0,0 +1,30 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +class TestIterator extends AsyncIterator { + async next() { + return {done: true, value: 'value'}; + } +} + +async function* gen(x) { yield x; } + +const methods = [ + iter => iter.map(x => x), + iter => iter.filter(x => true), + iter => iter.take(1), + iter => iter.drop(0), + iter => iter.asIndexedPairs(), + iter => iter.flatMap(gen), +]; + +(async () => { + for (const method of methods) { + const iterator = method(new TestIterator()); + const {done, value} = await iterator.next(); + assertEq(done, true); + assertEq(value, undefined); + } +})(); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-multiple-return-close-iterator-once.js b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-multiple-return-close-iterator-once.js new file mode 100644 index 0000000000..4ccb6fd4b1 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-multiple-return-close-iterator-once.js @@ -0,0 +1,64 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: Calling `.return()` on a lazy %AsyncIterator.prototype% method multiple times closes the source iterator once. +info: > + Iterator Helpers proposal 2.1.6 +features: [iterator-helpers] +---*/ + +class TestIterator extends AsyncIterator { + async next() { + return {done: false, value: 1}; + } + + closeCount = 0; + async return(value) { + this.closeCount++; + return {done: true, value}; + } +} + +async function* gen(x) { yield x; } + +const methods = [ + iter => iter.map(x => x), + iter => iter.filter(x => x), + iter => iter.take(1), + iter => iter.drop(0), + iter => iter.asIndexedPairs(), + iter => iter.flatMap(gen), +]; + +(async () => { + // Call `return` after stepping the iterator once: + for (const method of methods) { + const iter = new TestIterator(); + const iterHelper = method(iter); + + await iterHelper.next(); + assertEq(iter.closeCount, 0); + await iterHelper.return(); + assertEq(iter.closeCount, 1); + await iterHelper.return(); + assertEq(iter.closeCount, 1); + } + + // Call `return` before stepping the iterator: + for (const method of methods) { + const iter = new TestIterator(); + const iterHelper = method(iter); + + assertEq(iter.closeCount, 0); + await iterHelper.return(); + assertEq(iter.closeCount, 1); + await iterHelper.return(); + assertEq(iter.closeCount, 1); + } +})(); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-multiple-throw-close-iterator-once.js b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-multiple-throw-close-iterator-once.js new file mode 100644 index 0000000000..45e88be26a --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-multiple-throw-close-iterator-once.js @@ -0,0 +1,90 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: Calling `throw` on a lazy %AsyncIterator.prototype% method multiple times closes the source iterator once. +info: > + Iterator Helpers proposal 2.1.6 +features: [iterator-helpers] +---*/ + +class TestError extends Error {} + +class TestIterator extends AsyncIterator { + async next() { + return {done: false, value: 1}; + } + + closeCount = 0; + async return(value) { + this.closeCount++; + return {done: true, value}; + } +} + +async function* gen(x) { yield x; } + +const methods = [ + iter => iter.map(x => x), + iter => iter.filter(x => true), + iter => iter.take(Infinity), + iter => iter.drop(0), + iter => iter.asIndexedPairs(), + iter => iter.flatMap(gen), +]; + +(async () => { + // Call `throw` after stepping the iterator once: + for (const method of methods) { + const iter = new TestIterator(); + const iterHelper = method(iter); + + await iterHelper.next() + assertEq(iter.closeCount, 0); + + try { + await iterHelper.throw(new TestError()); + assertEq(true, false, 'Expected reject'); + } catch (exc) { + assertEq(exc instanceof TestError, true); + } + assertEq(iter.closeCount, 1); + + try { + await iterHelper.throw(new TestError()); + assertEq(true, false, 'Expected reject'); + } catch (exc) { + assertEq(exc instanceof TestError, true); + } + assertEq(iter.closeCount, 1); + } + + // Call `throw` before stepping the iterator: + for (const method of methods) { + const iter = new TestIterator(); + const iterHelper = method(iter); + + assertEq(iter.closeCount, 0); + + try { + await iterHelper.throw(new TestError()); + assertEq(true, false, 'Expected reject'); + } catch (exc) { + assertEq(exc instanceof TestError, true); + } + assertEq(iter.closeCount, 1); + + try { + await iterHelper.throw(new TestError()); + assertEq(true, false, 'Expected reject'); + } catch (exc) { + assertEq(exc instanceof TestError, true); + } + assertEq(iter.closeCount, 1); + } +})(); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-mutate-iterator-after-done.js b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-mutate-iterator-after-done.js new file mode 100644 index 0000000000..b9a37234a8 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-mutate-iterator-after-done.js @@ -0,0 +1,49 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +// +// + +/*--- +esid: pending +description: %AsyncIterator.prototype% methods ignore iterator mutation if already done. +info: > + Iterator Helpers proposal 2.1.6 +features: [iterator-helpers] +---*/ + +class TestIterator extends AsyncIterator { + values = [1, 2]; + async next() { + if (this.values.length == 0) + return {done: true}; + return {done: false, value: this.values.shift()}; + } +} + +function check({done, value}, expectedDone, expectedValue) { + assertEq(done, expectedDone); + assertEq(Array.isArray(value) ? value[1] : value, expectedValue); +} + +const methods = [ + ['map', x => x], + ['filter', x => true], + ['take', Infinity], + ['drop', 0], + ['asIndexedPairs', undefined], + ['flatMap', async function*(x) { yield x; }], +]; + +for (const [method, arg] of methods) { + (async () => { + const iter = new TestIterator(); + const iterHelper = iter[method](arg); + check(await iterHelper.next(), false, 1); + check(await iterHelper.next(), false, 2); + check(await iterHelper.next(), true, undefined); + iter.values.push(3); + check(await iterHelper.next(), true, undefined); + })(); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-mutate-iterator.js b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-mutate-iterator.js new file mode 100644 index 0000000000..876990d945 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-mutate-iterator.js @@ -0,0 +1,49 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +// +// + +/*--- +esid: pending +description: %AsyncIterator.prototype% methods work properly if the iterator has been mutated. +info: > + Iterator Helpers proposal 2.1.6 +features: [iterator-helpers] +---*/ + +class TestIterator extends AsyncIterator { + values = [1, 2]; + async next() { + if (this.values.length == 0) + return {done: true}; + return {done: false, value: this.values.shift()}; + } +} + +function check({done, value}, expectedDone, expectedValue) { + assertEq(done, expectedDone); + assertEq(Array.isArray(value) ? value[1] : value, expectedValue); +} + +const methods = [ + ['map', x => x], + ['filter', x => true], + ['take', Infinity], + ['drop', 0], + ['asIndexedPairs', undefined], + ['flatMap', async function*(x) { yield x; }], +]; + +for (const [method, arg] of methods) { + (async () => { + const iter = new TestIterator(); + const iterHelper = iter[method](arg); + check(await iterHelper.next(), false, 1); + check(await iterHelper.next(), false, 2); + iter.values.push(3); + check(await iterHelper.next(), false, 3); + check(await iterHelper.next(), true, undefined); + })(); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-not-close-iterator-next-reject.js b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-not-close-iterator-next-reject.js new file mode 100644 index 0000000000..43d84ae17d --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-not-close-iterator-next-reject.js @@ -0,0 +1,48 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: Lazy %AsyncIterator.prototype% methods don't close the iterator if `next` returns rejected promise. +info: > + AsyncIterator Helpers proposal 2.1.6 +features: [iterator-helpers] +---*/ + +class TestIterator extends AsyncIterator { + next() { + return Promise.reject('rejection'); + } + + closed = false; + async return(value) { + this.closed = true; + return {done: true, value}; + } +} + +async function* gen(x) { yield x; } +const methods = [ + iter => iter.map(x => x), + iter => iter.filter(x => x), + iter => iter.take(1), + iter => iter.drop(0), + iter => iter.asIndexedPairs(), + iter => iter.flatMap(gen), +]; + +for (const method of methods) { + const iterator = new TestIterator(); + assertEq(iterator.closed, false); + method(iterator).next().then( + _ => assertEq(true, false, 'Expected reject'), + err => { + assertEq(err, 'rejection'); + assertEq(iterator.closed, false); + }, + ); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-pass-through-lastValue.js b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-pass-through-lastValue.js new file mode 100644 index 0000000000..40da229ca6 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-pass-through-lastValue.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +class TestAsyncIterator extends AsyncIterator { + async next(value) { + return {done: false, value}; + } +} + +const methods = [ + iter => iter.map(x => x), + iter => iter.filter(x => true), + iter => iter.take(2), + iter => iter.drop(0), + iter => iter.asIndexedPairs(), +]; + +for (const method of methods) { + const iterator = new TestAsyncIterator(); + const iteratorHelper = method(iterator); + iteratorHelper.next().then( + _ => iteratorHelper.next('last value').then( + ({done, value}) => { + assertEq(done, false); + // Unwrap the return value from asIndexedPairs. + assertEq(Array.isArray(value) ? value[1] : value, 'last value'); + } + ), + ); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); + diff --git a/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-pass-value-through-chain.js b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-pass-value-through-chain.js new file mode 100644 index 0000000000..8b5506ee97 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-pass-value-through-chain.js @@ -0,0 +1,38 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +class TestAsyncIterator extends AsyncIterator { + async next(value) { + return {done: false, value}; + } +} + +const methods = [ + iter => iter.map(x => x), + iter => iter.filter(x => true), + iter => iter.take(2), + iter => iter.drop(0), + iter => iter.asIndexedPairs(), +]; + +for (const outerMethod of methods) { + for (const innerMethod of methods) { + const iterator = new TestAsyncIterator(); + const iteratorChain = outerMethod(innerMethod(iterator)); + iteratorChain.next().then( + _ => iteratorChain.next('last value').then( + ({done, value}) => { + assertEq(done, false); + // Unwrap the asIndexedPair return values. + while (Array.isArray(value)) { + value = value[1]; + } + assertEq(value, 'last value'); + } + ), + ); + } +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); + diff --git a/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-proxy-accesses.js b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-proxy-accesses.js new file mode 100644 index 0000000000..5892a41e5b --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-proxy-accesses.js @@ -0,0 +1,68 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +// + +/*--- +esid: pending +description: Lazy %AsyncIterator.prototype% methods access specified properties only. +info: > + Iterator Helpers proposal 2.1.6 +features: [iterator-helpers] +---*/ + +let log; +const handlerProxy = new Proxy({}, { + get: (target, key, receiver) => (...args) => { + log.push(`${key}: ${args.filter(x => typeof x != 'object').map(x => x.toString())}`); + return Reflect[key](...args); + }, +}); + +class TestIterator extends AsyncIterator { + value = 0; + async next() { + if (this.value < 1) + return new Proxy({done: false, value: this.value++}, handlerProxy); + return new Proxy({done: true, value: undefined}, handlerProxy); + } +} + +const methods = [ + ['map', x => x], + ['filter', x => true], + ['take', 4], + ['drop', 0], + ['asIndexedPairs', undefined], + ['flatMap', async function*(x) { yield x; }], +]; + +(async () => { + for (const [method, argument] of methods) { + log = []; + const iteratorProxy = new Proxy(new TestIterator(), handlerProxy); + const iteratorHelper = iteratorProxy[method](argument); + + await iteratorHelper.next(); + await iteratorHelper.next(); + const {done} = await iteratorHelper.next(); + assertEq(done, true); + assertEq( + log.join('\n'), + `get: ${method} +get: next +get: value +get: value +set: value,1 +getOwnPropertyDescriptor: value +defineProperty: value +get: then +get: done +get: value +get: value +get: then +get: done` + ); + } +})(); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-return-closes-iterator.js b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-return-closes-iterator.js new file mode 100644 index 0000000000..98a0902b75 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-return-closes-iterator.js @@ -0,0 +1,63 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: Calling `return` on a lazy %AsyncIterator.prototype% method closes the source iterator. +info: > + Iterator Helpers proposal 2.1.6 +features: [iterator-helpers] +---*/ + +class TestIterator extends AsyncIterator { + async next() { + return {done: false, value: 1}; + } + + closed = false; + async return(value) { + this.closed = true; + return {done: true, value}; + } +} + +async function* gen(x) { yield x; } + +const methods = [ + iter => iter.map(x => x), + iter => iter.filter(x => x), + iter => iter.take(1), + iter => iter.drop(0), + iter => iter.asIndexedPairs(), + iter => iter.flatMap(gen), +]; + +for (const method of methods) { + const iter = new TestIterator(); + const iterHelper = method(iter); + + iterHelper.next().then(() => { + assertEq(iter.closed, false); + iterHelper.return(0).then(({done, value}) => { + assertEq(iter.closed, true); + assertEq(done, true); + assertEq(value, 0); + }); + }); +} + +for (const method of methods) { + const iter = new TestIterator(); + const iterHelper = method(iter); + + assertEq(iter.closed, false); + iterHelper.return(0).then(({done, value}) => { + assertEq(iter.closed, true); + assertEq(done, true); + assertEq(value, 0); + }); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-return-new-iterator-result.js b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-return-new-iterator-result.js new file mode 100644 index 0000000000..02cae2740d --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-return-new-iterator-result.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: Lazy Iterator Helper methods return new iterator result objects. +info: > + Iterator Helpers proposal 2.1.6 +features: [iterator-helpers] +---*/ + +const iterResult = {done: false, value: 1, testProperty: 'test'}; +class TestIterator extends AsyncIterator { + async next() { + return iterResult; + } +} + +async function* gen(x) { yield x; } + +const methods = [ + iter => iter.map(x => x), + iter => iter.filter(x => true), + iter => iter.take(1), + iter => iter.drop(0), + iter => iter.asIndexedPairs(), + iter => iter.flatMap(gen), +]; + +// Call `return` before stepping the iterator: +for (const method of methods) { + const iter = new TestIterator(); + const iterHelper = method(iter); + iterHelper.next().then(result => { + assertEq(result == iterResult, false); + assertEq(result.testProperty, undefined); + }); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-throw-closes-iterator-before-next.js b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-throw-closes-iterator-before-next.js new file mode 100644 index 0000000000..4e9d9f6421 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-throw-closes-iterator-before-next.js @@ -0,0 +1,58 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: Calling `throw` on a lazy %AsyncIterator.prototype% method closes the source iterator. +info: > + Iterator Helpers proposal 2.1.6 +features: [iterator-helpers] +---*/ + +class TestError extends Error {} + +class TestIterator extends AsyncIterator { + async next() { + return {done: false, value: 1}; + } + + closed = false; + async return(value) { + this.closed = true; + return {done: true, value}; + } +} + +async function* gen(x) { yield x; } + +const methods = [ + iter => iter.map(x => x), + iter => iter.filter(x => x), + iter => iter.take(1), + iter => iter.drop(0), + iter => iter.asIndexedPairs(), + iter => iter.flatMap(gen), +]; + +for (const method of methods) { + const iter = new TestIterator(); + const iterHelper = method(iter); + + assertEq(iter.closed, false); + iterHelper.throw(new TestError()).then( + _ => assertEq(true, false, 'Expected reject.'), + err => { + assertEq(err instanceof TestError, true); + assertEq(iter.closed, true); + + iterHelper.next().then(({done, value}) => { + assertEq(done, true); + assertEq(value, undefined); + }); + }, + ); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-throw-eagerly-on-next-non-callable.js b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-throw-eagerly-on-next-non-callable.js new file mode 100644 index 0000000000..489887d020 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-throw-eagerly-on-next-non-callable.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: Lazy %AsyncIterator.prototype% methods throw eagerly when `next` is non-callable. +info: > + Iterator Helpers proposal 1.1.1 +features: [iterator-helpers] +---*/ + +async function* gen(x) { yield x; } +const methods = [ + next => AsyncIterator.prototype.map.bind({next}, x => x), + next => AsyncIterator.prototype.filter.bind({next}, x => x), + next => AsyncIterator.prototype.take.bind({next}, 1), + next => AsyncIterator.prototype.drop.bind({next}, 0), + next => AsyncIterator.prototype.asIndexedPairs.bind({next}), + next => AsyncIterator.prototype.flatMap.bind({next}, gen), +]; + +for (const method of methods) { + assertThrowsInstanceOf(method(0), TypeError); + assertThrowsInstanceOf(method(false), TypeError); + assertThrowsInstanceOf(method(undefined), TypeError); + assertThrowsInstanceOf(method(null), TypeError); + assertThrowsInstanceOf(method(''), TypeError); + assertThrowsInstanceOf(method(Symbol('')), TypeError); + assertThrowsInstanceOf(method({}), TypeError); + assertThrowsInstanceOf(method([]), TypeError); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-throw-eagerly-on-non-callable.js b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-throw-eagerly-on-non-callable.js new file mode 100644 index 0000000000..d8a9b390fa --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-throw-eagerly-on-non-callable.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: Lazy %AsyncIterator.prototype% methods throw eagerly when passed non-callables. +info: > + Iterator Helpers proposal 2.1.6 +features: [iterator-helpers] +---*/ + +async function* gen() {} + +const methods = [ + (iter, fn) => iter.map(fn), + (iter, fn) => iter.filter(fn), + (iter, fn) => iter.flatMap(fn), +]; + +for (const method of methods) { + assertThrowsInstanceOf(() => method(AsyncIterator.prototype, 0), TypeError); + assertThrowsInstanceOf(() => method(AsyncIterator.prototype, false), TypeError); + assertThrowsInstanceOf(() => method(AsyncIterator.prototype, undefined), TypeError); + assertThrowsInstanceOf(() => method(AsyncIterator.prototype, null), TypeError); + assertThrowsInstanceOf(() => method(AsyncIterator.prototype, ''), TypeError); + assertThrowsInstanceOf(() => method(AsyncIterator.prototype, Symbol('')), TypeError); + assertThrowsInstanceOf(() => method(AsyncIterator.prototype, {}), TypeError); + + assertThrowsInstanceOf(() => method(gen(), 0), TypeError); + assertThrowsInstanceOf(() => method(gen(), false), TypeError); + assertThrowsInstanceOf(() => method(gen(), undefined), TypeError); + assertThrowsInstanceOf(() => method(gen(), null), TypeError); + assertThrowsInstanceOf(() => method(gen(), ''), TypeError); + assertThrowsInstanceOf(() => method(gen(), Symbol('')), TypeError); + assertThrowsInstanceOf(() => method(gen(), {}), TypeError); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-throw-eagerly-on-non-iterator.js b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-throw-eagerly-on-non-iterator.js new file mode 100644 index 0000000000..1a61f5001a --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-throw-eagerly-on-non-iterator.js @@ -0,0 +1,31 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: Lazy %AsyncIterator.prototype% methods throw eagerly when called on non-iterators. +info: > + AsyncIterator Helpers proposal 1.1.1 +features: [iterator-helpers] +---*/ + +async function* gen(x) { yield x; } + +const methods = [ + iter => AsyncIterator.prototype.map.bind(iter, x => x), + iter => AsyncIterator.prototype.filter.bind(iter, x => x), + iter => AsyncIterator.prototype.take.bind(iter, 1), + iter => AsyncIterator.prototype.drop.bind(iter, 0), + iter => AsyncIterator.prototype.asIndexedPairs.bind(iter), + iter => AsyncIterator.prototype.flatMap.bind(iter, gen), +]; + +for (const method of methods) { + for (const value of [undefined, null, 0, false, '', Symbol(''), {}, []]) { + assertThrowsInstanceOf(method(value), TypeError); + } +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-throw-next-done-throws.js b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-throw-next-done-throws.js new file mode 100644 index 0000000000..276e59fc86 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-throw-next-done-throws.js @@ -0,0 +1,53 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: Lazy %AsyncIterator.prototype% methods throw if `next.done` throws. +info: > + AsyncIterator Helpers proposal 2.1.6 +features: [iterator-helpers] +---*/ + +class TestError extends Error {} +class TestAsyncIterator extends AsyncIterator { + async next() { + return { + get done() { + throw new TestError(); + } + }; + } + + closed = false; + async return() { + this.closed = true; + return {done: true}; + } +} + +async function* gen(x) { yield x; } +const methods = [ + iter => iter.map(x => x), + iter => iter.filter(x => x), + iter => iter.take(1), + iter => iter.drop(0), + iter => iter.asIndexedPairs(), + iter => iter.flatMap(gen), +]; + +for (const method of methods) { + const iterator = new TestAsyncIterator(); + assertEq(iterator.closed, false); + method(iterator).next().then( + _ => assertEq(true, false, 'Expected reject'), + err => { + assertEq(err instanceof TestError, true); + assertEq(iterator.closed, false); + }, + ); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-throw-next-not-object.js b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-throw-next-not-object.js new file mode 100644 index 0000000000..bb38a67000 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-throw-next-not-object.js @@ -0,0 +1,50 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: Lazy %AsyncIterator.prototype% methods throw if `next` call returns a non-object. +info: > + Iterator Helpers proposal 2.1.6 +features: [iterator-helpers] +---*/ + +class TestAsyncIterator extends AsyncIterator { + async next(value) { + return value; + } + + closed = false; + async return() { + this.closed = true; + return {done: true}; + } +} + +async function* gen(x) { yield x; } +const methods = [ + iter => iter.map(x => x), + iter => iter.filter(x => x), + iter => iter.take(1), + iter => iter.drop(0), + iter => iter.asIndexedPairs(), + iter => iter.flatMap(gen), +]; + +for (const method of methods) { + for (const value of [undefined, null, 0, false, '', Symbol('')]) { + const iterator = new TestAsyncIterator(); + assertEq(iterator.closed, false); + method(iterator).next(value).then( + _ => assertEq(true, false, 'Expected reject'), + err => { + assertEq(err instanceof TypeError, true); + assertEq(iterator.closed, false); + }, + ); + } +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-throw-on-reentry.js b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-throw-on-reentry.js new file mode 100644 index 0000000000..d7a582c6c1 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/lazy-methods-throw-on-reentry.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function* gen(x) { yield x; } + +const methods = ['map', 'filter', 'flatMap']; + +for (const method of methods) { + const iter = gen('value'); + const iterHelper = iter[method](x => iterHelper.next()); + iterHelper.next().then( + _ => assertEq(true, false, 'Expected reject.'), + err => assertEq(err instanceof TypeError, true), + ); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); + diff --git a/js/src/tests/non262/AsyncIterator/prototype/map/length.js b/js/src/tests/non262/AsyncIterator/prototype/map/length.js new file mode 100644 index 0000000000..4bd55f92e0 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/map/length.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +// + +/*--- +esid: pending +description: %AsyncIterator.prototype%.map length value and descriptor. +info: > + 17 ECMAScript Standard Built-in Objects +features: [iterator-helpers] +---*/ + +assertEq(AsyncIterator.prototype.map.length, 1); + +const propertyDescriptor = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype.map, 'length'); +assertEq(propertyDescriptor.value, 1); +assertEq(propertyDescriptor.enumerable, false); +assertEq(propertyDescriptor.writable, false); +assertEq(propertyDescriptor.configurable, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/map/map.js b/js/src/tests/non262/AsyncIterator/prototype/map/map.js new file mode 100644 index 0000000000..b3adb5cd6c --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/map/map.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function* gen() { + yield 1; + yield 2; + yield 3; +} + +const iter = gen().map(x => x**2); + +for (const v of [1, 4, 9]) { + iter.next().then( + ({done, value}) => { + assertEq(done, false); + assertEq(value, v); + } + ); +} + +iter.next().then(({done}) => assertEq(done, true)); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/map/name.js b/js/src/tests/non262/AsyncIterator/prototype/map/name.js new file mode 100644 index 0000000000..efb7181966 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/map/name.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +/*--- +esid: pending +description: %AsyncIterator.prototype%.map.name value and descriptor. +info: > + 17 ECMAScript Standard Built-in Objects +features: [iterator-helpers] +---*/ + +assertEq(AsyncIterator.prototype.map.name, 'map'); + +const propertyDescriptor = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype.map, 'name'); +assertEq(propertyDescriptor.value, 'map'); +assertEq(propertyDescriptor.enumerable, false); +assertEq(propertyDescriptor.writable, false); +assertEq(propertyDescriptor.configurable, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/accumulator-set-to-initial-value.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/accumulator-set-to-initial-value.js new file mode 100644 index 0000000000..943094aabc --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/accumulator-set-to-initial-value.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const reducer = (acc, _) => acc; +async function* gen() { + yield 1; + yield 2; + yield 3; +} + +gen().reduce(reducer, 0).then(value => assertEq(value, 0)); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/async-writes.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/async-writes.js new file mode 100644 index 0000000000..2328cc3521 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/async-writes.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +let x = {a: () => true}; + +async function* gen() { + yield x.a(); + yield x.a(); +} + +gen().reduce(() => {}, 0).then( + () => assertEq(true, false, 'expected error'), + err => assertEq(err instanceof Error, true), +); + +x.a = () => { + throw Error(); +}; + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/check-fn-after-getting-iterator.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/check-fn-after-getting-iterator.js new file mode 100644 index 0000000000..4a5484f786 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/check-fn-after-getting-iterator.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +const log = []; +const handlerProxy = new Proxy({}, { + get: (target, key, receiver) => (...args) => { + log.push(`${key}: ${args[1]?.toString()}`); + return Reflect[key](...args); + }, +}); + +class TestIterator extends AsyncIterator { + next() { + return Promise.resolve({ done: this.closed }); + } +} + +const iter = new Proxy(new TestIterator(), handlerProxy); +iter.reduce(1).then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof TypeError, true); + assertEq( + log.join('\n'), + `get: reduce +get: next` + ); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/descriptor.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/descriptor.js new file mode 100644 index 0000000000..6472c1a14d --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/descriptor.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +/*--- + Descriptor property of AsyncIterator.prototype.reduce +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype, 'reduce'); +assertEq(typeof propDesc.value, 'function'); +assertEq(propDesc.writable, true); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/empty-iterator-without-initial-value-throws.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/empty-iterator-without-initial-value-throws.js new file mode 100644 index 0000000000..c54fccba20 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/empty-iterator-without-initial-value-throws.js @@ -0,0 +1,9 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function* gen() {} +gen().reduce((x, y) => x + y).then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof TypeError, true); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/error-from-correct-realm.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/error-from-correct-realm.js new file mode 100644 index 0000000000..16c0ac51a9 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/error-from-correct-realm.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const otherGlobal = newGlobal({newCompartment: true}); +assertEq(TypeError !== otherGlobal.TypeError, true); + +async function *gen() {} + +gen().reduce().then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof TypeError, true); +}); + +otherGlobal.AsyncIterator.prototype.reduce.call(gen()).then(() => assertEq(true, false, 'expected error'), err => { + assertEq( + err instanceof otherGlobal.TypeError, + true, + 'TypeError comes from the realm of the method.', + ); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/interleaving-calls.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/interleaving-calls.js new file mode 100644 index 0000000000..8961c69903 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/interleaving-calls.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const log = []; +async function* gen(n) { + log.push(`${n}`); + yield 1; + log.push(`${n}`); + yield 2; +} + +Promise.all([gen(1).reduce(() => {}, 0), gen(2).reduce(() => {}, 0)]).then( + () => { + assertEq( + log.join(' '), + '1 2 1 2', + ); + }, + err => { + throw err; + } +); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/iterator-empty-return-initial-value.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/iterator-empty-return-initial-value.js new file mode 100644 index 0000000000..b664d25729 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/iterator-empty-return-initial-value.js @@ -0,0 +1,9 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const reducer = (x, y) => 0; +async function *gen() {} + +gen().reduce(reducer, 1).then(result => assertEq(result, 1)); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/iterator-next-return-non-object-throws.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/iterator-next-return-non-object-throws.js new file mode 100644 index 0000000000..57c244d603 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/iterator-next-return-non-object-throws.js @@ -0,0 +1,31 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +class TestIterator extends AsyncIterator { + constructor(value) { + super(); + this.value = value; + } + + next() { + return Promise.resolve(this.value); + } +} + +const sum = (x, y) => x + y; +function check(value) { + const iter = new TestIterator(value); + iter.reduce(sum).then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof TypeError, true); + }); +} + +check(); +check(undefined); +check(null); +check(0); +check(false); +check(''); +check(Symbol('')); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/left-associative.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/left-associative.js new file mode 100644 index 0000000000..91147a1fba --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/left-associative.js @@ -0,0 +1,15 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function* gen() { + yield 1; + yield 2; + yield 3; +} + +gen().reduce((x, y) => `(${x}+${y})`, 0) + .then(result => assertEq(result, '(((0+1)+2)+3)')); +gen().reduce((x, y) => `(${x}+${y})`) + .then(result => assertEq(result, '((1+2)+3)')); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/length.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/length.js new file mode 100644 index 0000000000..022df65164 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/length.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +/*--- + The `length` property of AsyncIterator.prototype.reduce. +info: | + ES7 section 17: Unless otherwise specified, the length property of a built-in + Function object has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype.reduce, 'length'); +assertEq(propDesc.value, 1); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/name.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/name.js new file mode 100644 index 0000000000..aada19b46d --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/name.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +/*--- + `name` property of AsyncIterator.prototype.reduce. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype.reduce, 'name'); +assertEq(propDesc.value, 'reduce'); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/next-throws-iterator-not-closed.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/next-throws-iterator-not-closed.js new file mode 100644 index 0000000000..796cdb1895 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/next-throws-iterator-not-closed.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +class TestIterator extends AsyncIterator { + next() { + throw new Error(); + } + + closed = false; + return() { + this.closed = true; + } +} + +const sum = (x, y) => x + y; +const iter = new TestIterator(); + +assertEq(iter.closed, false); +iter.reduce(sum).then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof Error, true); + assertEq(iter.closed, false); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/no-initial-value-set-accumulator-to-first-value.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/no-initial-value-set-accumulator-to-first-value.js new file mode 100644 index 0000000000..0e480dbe4a --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/no-initial-value-set-accumulator-to-first-value.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const reducer = (acc, _) => acc; +async function* gen() { + yield 1; + yield 2; + yield 3; +} + +gen().reduce(reducer).then(result => assertEq(result, 1)); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/proxy.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/proxy.js new file mode 100644 index 0000000000..b1e6d52495 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/proxy.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +// +// This test checks that %Iterator.prototype%.reduce only gets the `next` method off of the +// iterator once, and never accesses the @@iterator property. +const log = []; +const handlerProxy = new Proxy({}, { + get: (target, key, receiver) => (...args) => { + log.push(`${key}: ${args[1]?.toString()}`); + return Reflect[key](...args); + }, +}); + +class Counter extends AsyncIterator { + value = 0; + next() { + const value = this.value; + if (value < 2) { + this.value = value + 1; + return Promise.resolve({done: false, value}); + } + return Promise.resolve({done: true}); + } +} + +const iter = new Proxy(new Counter(), handlerProxy); +iter.reduce((x, y) => x + y).then(() => { + assertEq( + log.join('\n'), + `get: reduce +get: next +get: value +set: value +getOwnPropertyDescriptor: value +defineProperty: value +get: value +set: value +getOwnPropertyDescriptor: value +defineProperty: value +get: value` + ); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/reduce.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/reduce.js new file mode 100644 index 0000000000..d2382e4d53 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/reduce.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const reducer = (acc, value) => acc + value; +async function* gen() { + yield 1; + yield 2; + yield 3; +} + +gen().reduce(reducer, 0).then(result => assertEq(result, 6)); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/reducer-not-callable-throws.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/reducer-not-callable-throws.js new file mode 100644 index 0000000000..c7fb2005d8 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/reducer-not-callable-throws.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function *gen() {} + +function check(fn) { + gen().reduce(fn).then(() => { + throw new Error('every should have thrown'); + }, + err => { + assertEq(err instanceof TypeError, true); + }); +} + +check(); +check(undefined); +check(null); +check(0); +check(false); +check(''); +check(Symbol('')); +check({}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/reducer-throws-iterator-closed.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/reducer-throws-iterator-closed.js new file mode 100644 index 0000000000..2a55a89850 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/reducer-throws-iterator-closed.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +class TestIterator extends AsyncIterator { + next() { + return Promise.resolve({ done: this.closed, value: undefined }); + } + + closed = false; + return() { + this.closed = true; + } +} + +const reducer = (x, y) => { throw new Error(); }; +const iter = new TestIterator(); + +assertEq(iter.closed, false); +iter.reduce(reducer).then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof Error, true); + assertEq(iter.closed, true); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/this-not-iterator-throws.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/this-not-iterator-throws.js new file mode 100644 index 0000000000..7f95920fbd --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/this-not-iterator-throws.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const sum = (x, y) => x + y; +function check(x) { + AsyncIterator.prototype.reduce.call(x, sum).then( + () => assertEq(true, false, 'expected error'), + err => { + assertEq(err instanceof TypeError, true); + } + ); +} + +check(); +check(undefined); +check({}); +check({next: 0}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/reduce/value-throws-iterator-not-closed.js b/js/src/tests/non262/AsyncIterator/prototype/reduce/value-throws-iterator-not-closed.js new file mode 100644 index 0000000000..bfe4a9213f --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/reduce/value-throws-iterator-not-closed.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +class TestError extends Error {} +class TestIterator extends AsyncIterator { + next() { + return Promise.resolve({ + done: false, + get value() { + throw new TestError(); + } + }); + } + + closed = false; + return() { + closed = true; + } +} + +const iterator = new TestIterator(); +assertEq(iterator.closed, false, 'iterator starts unclosed'); +iterator.reduce((x, y) => x + y, 0).then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof TestError, true); + assertEq(iterator.closed, false, 'iterator remains unclosed'); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/some/async-writes.js b/js/src/tests/non262/AsyncIterator/prototype/some/async-writes.js new file mode 100644 index 0000000000..384bf2e115 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/some/async-writes.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +let x = {a: () => true}; + +async function* gen() { + yield x.a(); + yield x.a(); +} + +gen().some(() => {}).then( + () => assertEq(true, false, 'expected error'), + err => assertEq(err instanceof Error, true), +); + +x.a = () => { + throw Error(); +}; + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/some/check-fn-after-getting-iterator.js b/js/src/tests/non262/AsyncIterator/prototype/some/check-fn-after-getting-iterator.js new file mode 100644 index 0000000000..41dd30bee0 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/some/check-fn-after-getting-iterator.js @@ -0,0 +1,31 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +const log = []; +const handlerProxy = new Proxy({}, { + get: (target, key, receiver) => (...args) => { + log.push(`${key}: ${args[1]?.toString()}`); + return Reflect[key](...args); + }, +}); + +class TestIterator extends AsyncIterator { + next() { + return Promise.resolve({done: true}); + } +} + +async function* gen() { + yield 1; +} + +const iter = new Proxy(new TestIterator(), handlerProxy); +iter.some(1).then(() => assertEq(true, false, 'expected error'), err => assertEq(err instanceof TypeError, true)); + +assertEq( + log.join('\n'), + `get: some +get: next` +); + + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/some/coerce-result-to-boolean.js b/js/src/tests/non262/AsyncIterator/prototype/some/coerce-result-to-boolean.js new file mode 100644 index 0000000000..8b56511040 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/some/coerce-result-to-boolean.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function* gen(value) { + yield value; +} +const fn = x => x; +function check(value, expected) { + gen(value).some(fn).then(result => assertEq(result, expected)); +} + +check(true, true); +check(1, true); +check([], true); +check({}, true); +check('test', true); + +check(false, false); +check(0, false); +check('', false); +check(null, false); +check(undefined, false); +check(NaN, false); +check(-0, false); +check(0n, false); +check(createIsHTMLDDA(), false); +check(Promise.resolve(false), false); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/some/descriptor.js b/js/src/tests/non262/AsyncIterator/prototype/some/descriptor.js new file mode 100644 index 0000000000..d9f5ef8fb7 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/some/descriptor.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +/*--- + Descriptor property of AsyncIterator.prototype.some +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype, 'some'); +assertEq(typeof propDesc.value, 'function'); +assertEq(propDesc.writable, true); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/some/error-from-correct-realm.js b/js/src/tests/non262/AsyncIterator/prototype/some/error-from-correct-realm.js new file mode 100644 index 0000000000..bb4b637c1a --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/some/error-from-correct-realm.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const otherGlobal = newGlobal({newCompartment: true}); +assertEq(TypeError !== otherGlobal.TypeError, true); + +async function *gen() {} + +gen().some().then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof TypeError, true); +}); + +otherGlobal.AsyncIterator.prototype.some.call(gen()).then(() => assertEq(true, false, 'expected error'), err => { + assertEq( + err instanceof otherGlobal.TypeError, + true, + 'TypeError comes from the realm of the method.', + ); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/some/fn-not-callable-throws.js b/js/src/tests/non262/AsyncIterator/prototype/some/fn-not-callable-throws.js new file mode 100644 index 0000000000..74a11ceebf --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/some/fn-not-callable-throws.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function *gen() { + yield 1; +} + +function check(fn) { + gen().some(fn).then( + () => { + throw new Error('every should have thrown'); + }, + err => { + assertEq(err instanceof TypeError, true); + } + ); +} + +check(); +check(undefined); +check(null); +check(0); +check(false); +check(''); +check(Symbol('')); +check({}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/some/fn-throws-close-iterator.js b/js/src/tests/non262/AsyncIterator/prototype/some/fn-throws-close-iterator.js new file mode 100644 index 0000000000..bdf5119f57 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/some/fn-throws-close-iterator.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +class TestIterator extends AsyncIterator { + next() { + return Promise.resolve({ done: this.closed }); + } + + closed = false; + return() { + this.closed = true; + } +} + +const fn = () => { throw new Error(); }; +const iter = new TestIterator(); + +assertEq(iter.closed, false); +iter.some(fn).then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof Error, true); + assertEq(iter.closed, true); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/some/interleaving-calls.js b/js/src/tests/non262/AsyncIterator/prototype/some/interleaving-calls.js new file mode 100644 index 0000000000..d5882b9532 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/some/interleaving-calls.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const log = []; +async function* gen(n) { + log.push(`${n}`); + yield 1; + log.push(`${n}`); + yield 2; +} + +Promise.all([gen(1).some(() => {}), gen(2).some(() => {})]).then( + () => { + assertEq( + log.join(' '), + '1 2 1 2', + ); + }, + err => { + throw err; + } +); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/some/length.js b/js/src/tests/non262/AsyncIterator/prototype/some/length.js new file mode 100644 index 0000000000..ce86dc8b2f --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/some/length.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +/*--- + The `length` property of AsyncIterator.prototype.some. +info: | + ES7 section 17: Unless otherwise specified, the length property of a built-in + Function object has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype.some, 'length'); +assertEq(propDesc.value, 1); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/some/name.js b/js/src/tests/non262/AsyncIterator/prototype/some/name.js new file mode 100644 index 0000000000..f2e84a139c --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/some/name.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +/*--- + `name` property of AsyncIterator.prototype.some. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype.some, 'name'); +assertEq(propDesc.value, 'some'); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/some/next-throws-iterator-not-closed.js b/js/src/tests/non262/AsyncIterator/prototype/some/next-throws-iterator-not-closed.js new file mode 100644 index 0000000000..89574e0f8e --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/some/next-throws-iterator-not-closed.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +class TestIterator extends AsyncIterator { + next() { + throw new Error(); + } + + closed = false; + return() { + this.closed = true; + } +} + +const fn = () => {}; +const iter = new TestIterator(); + +assertEq(iter.closed, false); +iter.some(fn).then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof Error, true); + assertEq(iter.closed, false); +}); +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/some/proxy.js b/js/src/tests/non262/AsyncIterator/prototype/some/proxy.js new file mode 100644 index 0000000000..6ae089ae38 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/some/proxy.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +// +// This test checks that %Iterator.prototype%.some only gets the `next` method off of the +// iterator once, and never accesses the @@iterator property. +const log = []; +const handlerProxy = new Proxy({}, { + get: (target, key, receiver) => (...args) => { + log.push(`${key}: ${args[1]?.toString()}`); + return Reflect[key](...args); + }, +}); + +class Counter extends AsyncIterator { + value = 0; + next() { + const value = this.value; + if (value < 2) { + this.value = value + 1; + return Promise.resolve({done: false, value}); + } + return Promise.resolve({done: true}); + } +} + +const iter = new Proxy(new Counter(), handlerProxy); +iter.some(x => x % 2 == 1).then(value => { + assertEq(value, true); + + assertEq( + log.join('\n'), + `get: some +get: next +get: value +set: value +getOwnPropertyDescriptor: value +defineProperty: value +get: value +set: value +getOwnPropertyDescriptor: value +defineProperty: value +get: return` + ); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/some/return-false-if-none-match.js b/js/src/tests/non262/AsyncIterator/prototype/some/return-false-if-none-match.js new file mode 100644 index 0000000000..118436d70b --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/some/return-false-if-none-match.js @@ -0,0 +1,16 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function* gen() { + yield 1; + yield 3; + yield 5; +} +const fn = x => x % 2 == 0; + +gen().some(fn).then(result => assertEq(result, false)); + +async function* empty() {} +empty().some(x => x).then(result => assertEq(result, false)); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/some/short-circuit-on-true.js b/js/src/tests/non262/AsyncIterator/prototype/some/short-circuit-on-true.js new file mode 100644 index 0000000000..3d7250b9a2 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/some/short-circuit-on-true.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function* gen() { + yield 1; + yield 2; + yield 3; +} +const log = []; +const fn = (value) => { + log.push(value.toString()); + return value % 2 == 0; +}; + +gen().some(fn).then(result => { + assertEq(result, true); + assertEq(log.join(','), '1,2'); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/some/this-not-iterator-throws.js b/js/src/tests/non262/AsyncIterator/prototype/some/this-not-iterator-throws.js new file mode 100644 index 0000000000..1233fc371c --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/some/this-not-iterator-throws.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const fn = x => x; +function check(x) { + AsyncIterator.prototype.some.call(x, fn).then( + () => assertEq(true, false, 'expected error'), + err => { + assertEq(err instanceof TypeError, true); + } + ); +} + +check(); +check(undefined); +check({}); +check({next: 0}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/some/value-throws-iterator-not-closed.js b/js/src/tests/non262/AsyncIterator/prototype/some/value-throws-iterator-not-closed.js new file mode 100644 index 0000000000..f7a344eea4 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/some/value-throws-iterator-not-closed.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +class TestError extends Error {} +class TestIterator extends AsyncIterator { + next() { + return Promise.resolve({ + done: false, + get value() { + throw new TestError(); + } + }); + } + + closed = false; + return() { + closed = true; + } +} + +const iterator = new TestIterator(); +assertEq(iterator.closed, false, 'iterator starts unclosed'); +iterator.some(x => x).then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof TestError, true); + assertEq(iterator.closed, false, 'iterator remains unclosed'); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/take-drop-throw-eagerly-on-negative.js b/js/src/tests/non262/AsyncIterator/prototype/take-drop-throw-eagerly-on-negative.js new file mode 100644 index 0000000000..f21c78e650 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/take-drop-throw-eagerly-on-negative.js @@ -0,0 +1,30 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: `take` and `drop` throw eagerly when passed negative numbers, after rounding towards 0. +info: > + Iterator Helpers proposal 2.1.6.4 and 2.1.6.5 +features: [iterator-helpers] +---*/ + +async function* gen() {} +const iter = gen(); +const methods = [ + value => iter.take(value), + value => iter.drop(value), +]; + +for (const method of methods) { + assertThrowsInstanceOf(() => method(-1), RangeError); + assertThrowsInstanceOf(() => method(-Infinity), RangeError); + + // Both -0 and -0.9 round towards 0. + method(-0); + method(-0.9); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/take-drop-throw-eagerly-on-non-integer.js b/js/src/tests/non262/AsyncIterator/prototype/take-drop-throw-eagerly-on-non-integer.js new file mode 100644 index 0000000000..a81b407afc --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/take-drop-throw-eagerly-on-non-integer.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: `take` and `drop` throw eagerly when passed values that can't be converted to numbers. +info: > + Iterator Helpers proposal 2.1.6.4 and 2.1.6.5 +features: [iterator-helpers] +---*/ + +async function* gen() {} +const iter = gen(); +const methods = [ + value => iter.take(value), + value => iter.drop(value), +]; + +const objectWithToPrimitive = { + [Symbol.toPrimitive]() { + return {}; + } +}; + +for (const method of methods) { + assertThrowsInstanceOf(() => method(0n), TypeError); + assertThrowsInstanceOf(() => method(Symbol('')), TypeError); + assertThrowsInstanceOf(() => method(objectWithToPrimitive), TypeError); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/take/close-iterator-when-none-remaining.js b/js/src/tests/non262/AsyncIterator/prototype/take/close-iterator-when-none-remaining.js new file mode 100644 index 0000000000..6ae3e34b5d --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/take/close-iterator-when-none-remaining.js @@ -0,0 +1,45 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: %AsyncIterator.prototype%.take closes the iterator when remaining is 0. +info: > + Iterator Helpers proposal 2.1.6.4 +features: [iterator-helpers] +---*/ + +class TestIterator extends AsyncIterator { + async next() { + return {done: false, value: 'value'}; + } + + closed = false; + async return() { + this.closed = true; + return {done: true}; + } +} + +const iter = new TestIterator(); +const iterTake = iter.take(1); + +iterTake.next().then( + ({done, value}) => { + assertEq(done, false); + assertEq(value, 'value'); + assertEq(iter.closed, false); + + iterTake.next().then( + ({done, value}) => { + assertEq(done, true); + assertEq(value, undefined); + assertEq(iter.closed, true); + } + ); + } +); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/take/length.js b/js/src/tests/non262/AsyncIterator/prototype/take/length.js new file mode 100644 index 0000000000..0daf649a58 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/take/length.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +// + +/*--- +esid: pending +description: %AsyncIterator.prototype%.take length value and descriptor. +info: > + 17 ECMAScript Standard Built-in Objects +features: [iterator-helpers] +---*/ + +assertEq(AsyncIterator.prototype.take.length, 1); + +const propertyDescriptor = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype.take, 'length'); +assertEq(propertyDescriptor.value, 1); +assertEq(propertyDescriptor.enumerable, false); +assertEq(propertyDescriptor.writable, false); +assertEq(propertyDescriptor.configurable, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/take/name.js b/js/src/tests/non262/AsyncIterator/prototype/take/name.js new file mode 100644 index 0000000000..6d126390fb --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/take/name.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +/*--- +esid: pending +description: %AsyncIterator.prototype%.take.name value and descriptor. +info: > + 17 ECMAScript Standard Built-in Objects +features: [iterator-helpers] +---*/ + +assertEq(AsyncIterator.prototype.take.name, 'take'); + +const propertyDescriptor = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype.take, 'name'); +assertEq(propertyDescriptor.value, 'take'); +assertEq(propertyDescriptor.enumerable, false); +assertEq(propertyDescriptor.writable, false); +assertEq(propertyDescriptor.configurable, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/take/take-more-than-available.js b/js/src/tests/non262/AsyncIterator/prototype/take/take-more-than-available.js new file mode 100644 index 0000000000..65355704ae --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/take/take-more-than-available.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +// +// +/*--- +esid: pending +description: %AsyncIterator.prototype%.take returns if the iterator is done. +info: > + Iterator Helpers proposal 2.1.6.4 + 2. Repeat, + ... + c. Let next be ? Await(? IteratorNext(iterated, lastValue)). + d. If ? IteratorComplete(next) is false, return undefined. +features: [iterator-helpers] +---*/ + +async function* gen(values) { + yield* values; +} + +(async () => { + const iter = gen([1, 2]).take(10); + for (const expected of [1, 2]) { + const result = await iter.next(); + assertEq(result.value, expected); + assertEq(result.done, false); + } + const result = await iter.next(); + assertEq(result.value, undefined); + assertEq(result.done, true); +})(); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/take/take.js b/js/src/tests/non262/AsyncIterator/prototype/take/take.js new file mode 100644 index 0000000000..a734da8c2c --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/take/take.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function* gen() { + yield 1; + yield 2; + yield 3; +} + +let iter = gen().take(2); + +for (const v of [1, 2]) { + iter.next().then( + ({done, value}) => { + assertEq(done, false); + assertEq(value, v); + } + ); +} + +iter.next().then(({done}) => assertEq(done, true)); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/toArray/async-writes.js b/js/src/tests/non262/AsyncIterator/prototype/toArray/async-writes.js new file mode 100644 index 0000000000..8246d8d4ed --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/toArray/async-writes.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +let x = {a: () => true}; + +async function* gen() { + yield x.a(); + yield x.a(); +} + +gen().toArray().then( + () => assertEq(true, false, 'expected error'), + err => assertEq(err instanceof Error, true), +); + +x.a = () => { + throw Error(); +}; + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/toArray/create-in-current-realm.js b/js/src/tests/non262/AsyncIterator/prototype/toArray/create-in-current-realm.js new file mode 100644 index 0000000000..6f0b69f8ad --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/toArray/create-in-current-realm.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const otherGlobal = newGlobal({newCompartment: true}); + +async function* gen() { + yield 1; + yield 2; + yield 3; +} + +gen().toArray().then(array => { + assertEq(array instanceof Array, true); + assertEq(array instanceof otherGlobal.Array, false); +}); + +otherGlobal.AsyncIterator.prototype.toArray.call(gen()).then(array => { + assertEq(array instanceof Array, false); + assertEq(array instanceof otherGlobal.Array, true); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/toArray/descriptor.js b/js/src/tests/non262/AsyncIterator/prototype/toArray/descriptor.js new file mode 100644 index 0000000000..58c7a13872 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/toArray/descriptor.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +/*--- + Descriptor property of AsyncIterator.prototype.toArray +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype, 'toArray'); +assertEq(typeof propDesc.value, 'function'); +assertEq(propDesc.writable, true); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/toArray/interleaving-calls.js b/js/src/tests/non262/AsyncIterator/prototype/toArray/interleaving-calls.js new file mode 100644 index 0000000000..88e3fcd5e8 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/toArray/interleaving-calls.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +const log = []; +async function* gen(n) { + log.push(`${n}`); + yield 1; + log.push(`${n}`); + yield 2; +} + +Promise.all([gen(1).toArray(), gen(2).toArray()]).then( + () => { + assertEq( + log.join(' '), + '1 2 1 2', + ); + }, + err => { + throw err; + } +); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/toArray/iterator-empty.js b/js/src/tests/non262/AsyncIterator/prototype/toArray/iterator-empty.js new file mode 100644 index 0000000000..d8eec0454d --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/toArray/iterator-empty.js @@ -0,0 +1,10 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function* gen() {} +gen().toArray().then(array => { + assertEq(Array.isArray(array), true); + assertEq(array.length, 0); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/toArray/length.js b/js/src/tests/non262/AsyncIterator/prototype/toArray/length.js new file mode 100644 index 0000000000..f0467d5fc3 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/toArray/length.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +/*--- + The `length` property of AsyncIterator.prototype.toArray. +info: | + ES7 section 17: Unless otherwise specified, the length property of a built-in + Function object has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype.toArray, 'length'); +assertEq(propDesc.value, 0); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/toArray/name.js b/js/src/tests/non262/AsyncIterator/prototype/toArray/name.js new file mode 100644 index 0000000000..63cdf4c201 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/toArray/name.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +/*--- + `name` property of AsyncIterator.prototype.toArray. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(AsyncIterator.prototype.toArray, 'name'); +assertEq(propDesc.value, 'toArray'); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/toArray/next-throws.js b/js/src/tests/non262/AsyncIterator/prototype/toArray/next-throws.js new file mode 100644 index 0000000000..d998f83e83 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/toArray/next-throws.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +class TestIterator extends AsyncIterator { + next() { + throw new Error(); + } + + closed = false; + return() { + this.closed = true; + } +} + +const iter = new TestIterator(); + +assertEq(iter.closed, false); +iter.toArray().then(() => assertEq(true, false, 'expected error'), err => { + assertEq(err instanceof Error, true); + assertEq(iter.closed, false); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/toArray/proxy.js b/js/src/tests/non262/AsyncIterator/prototype/toArray/proxy.js new file mode 100644 index 0000000000..b82af6628e --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/toArray/proxy.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) +// +// This test checks that %Iterator.prototype%.toArray only gets the `next` method off of the +// iterator once, and never accesses the @@iterator property. +const log = []; +const handlerProxy = new Proxy({}, { + get: (target, key, receiver) => (...args) => { + log.push(`${key}: ${args[1]?.toString()}`); + return Reflect[key](...args); + }, +}); + +class Counter extends AsyncIterator { + value = 0; + next() { + const value = this.value; + if (value < 2) { + this.value = value + 1; + return Promise.resolve({done: false, value}); + } + return Promise.resolve({done: true}); + } +} + +const iter = new Proxy(new Counter(), handlerProxy); +iter.toArray().then(() => { + assertEq( + log.join('\n'), + `get: toArray +get: next +get: value +set: value +getOwnPropertyDescriptor: value +defineProperty: value +get: value +set: value +getOwnPropertyDescriptor: value +defineProperty: value +get: value` + ); +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/toArray/this-not-iterator-throws.js b/js/src/tests/non262/AsyncIterator/prototype/toArray/this-not-iterator-throws.js new file mode 100644 index 0000000000..9846c33ee5 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/toArray/this-not-iterator-throws.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + + +function check(x) { + AsyncIterator.prototype.toArray.call(x).then( + () => { + throw new Error('check should have been rejected'); + }, + err => { + assertEq(err instanceof TypeError, true); + } + ); +} + +check(); +check(undefined); +check({}); +check({next: 0}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/toArray/toArray.js b/js/src/tests/non262/AsyncIterator/prototype/toArray/toArray.js new file mode 100644 index 0000000000..0a91e4d95d --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/toArray/toArray.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +async function* gen() { + yield 1; + yield 2; + yield 3; +} +assertEq(Array.isArray(gen()), false); + +gen().toArray().then(array => { + assertEq(Array.isArray(array), true); + assertEq(array.length, 3); + + const expected = [1, 2, 3]; + for (const item of array) { + const expect = expected.shift(); + assertEq(item, expect); + } +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/AsyncIterator/prototype/toArray/value-throws-iterator-not-closed.js b/js/src/tests/non262/AsyncIterator/prototype/toArray/value-throws-iterator-not-closed.js new file mode 100644 index 0000000000..a00f780185 --- /dev/null +++ b/js/src/tests/non262/AsyncIterator/prototype/toArray/value-throws-iterator-not-closed.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +class TestError extends Error {} +class TestIterator extends AsyncIterator { + next() { + return Promise.resolve({ + done: false, + get value() { + throw new TestError(); + } + }); + } + + closed = false; + return() { + closed = true; + } +} + +const iterator = new TestIterator(); +assertEq(iterator.closed, false, 'iterator starts unclosed'); +iterator.toArray().then( + () => { + throw new Error('toArray should have thrown'); + }, + err => { + assertEq(err instanceof TestError, true); + assertEq(iterator.closed, false, 'iterator remains unclosed'); + } +); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Atomics/browser.js b/js/src/tests/non262/Atomics/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Atomics/cross-compartment.js b/js/src/tests/non262/Atomics/cross-compartment.js new file mode 100644 index 0000000000..8ef46bda38 --- /dev/null +++ b/js/src/tests/non262/Atomics/cross-compartment.js @@ -0,0 +1,109 @@ +// |reftest| skip-if(!this.Atomics||!this.SharedArrayBuffer) fails-if(!xulRuntime.shell) + +const otherGlobal = newGlobal(); + +const intArrayConstructors = [ + otherGlobal.Int32Array, + otherGlobal.Int16Array, + otherGlobal.Int8Array, + otherGlobal.Uint32Array, + otherGlobal.Uint16Array, + otherGlobal.Uint8Array, +]; + +// Atomics.load +for (let TA of intArrayConstructors) { + let ta = new TA(new otherGlobal.SharedArrayBuffer(4)); + ta[0] = 1; + + assertEq(Atomics.load(ta, 0), 1); +} + +// Atomics.store +for (let TA of intArrayConstructors) { + let ta = new TA(new otherGlobal.SharedArrayBuffer(4)); + + Atomics.store(ta, 0, 1); + + assertEq(ta[0], 1); +} + +// Atomics.compareExchange +for (let TA of intArrayConstructors) { + let ta = new TA(new otherGlobal.SharedArrayBuffer(4)); + ta[0] = 1; + + let val = Atomics.compareExchange(ta, 0, 1, 2); + + assertEq(val, 1); + assertEq(ta[0], 2); +} + +// Atomics.exchange +for (let TA of intArrayConstructors) { + let ta = new TA(new otherGlobal.SharedArrayBuffer(4)); + ta[0] = 1; + + let val = Atomics.exchange(ta, 0, 2); + + assertEq(val, 1); + assertEq(ta[0], 2); +} + +// Atomics.add +for (let TA of intArrayConstructors) { + let ta = new TA(new otherGlobal.SharedArrayBuffer(4)); + ta[0] = 1; + + let val = Atomics.add(ta, 0, 2); + + assertEq(val, 1); + assertEq(ta[0], 3); +} + +// Atomics.sub +for (let TA of intArrayConstructors) { + let ta = new TA(new otherGlobal.SharedArrayBuffer(4)); + ta[0] = 3; + + let val = Atomics.sub(ta, 0, 2); + + assertEq(val, 3); + assertEq(ta[0], 1); +} + +// Atomics.and +for (let TA of intArrayConstructors) { + let ta = new TA(new otherGlobal.SharedArrayBuffer(4)); + ta[0] = 3; + + let val = Atomics.and(ta, 0, 1); + + assertEq(val, 3); + assertEq(ta[0], 1); +} + +// Atomics.or +for (let TA of intArrayConstructors) { + let ta = new TA(new otherGlobal.SharedArrayBuffer(4)); + ta[0] = 2; + + let val = Atomics.or(ta, 0, 1); + + assertEq(val, 2); + assertEq(ta[0], 3); +} + +// Atomics.xor +for (let TA of intArrayConstructors) { + let ta = new TA(new otherGlobal.SharedArrayBuffer(4)); + ta[0] = 3; + + let val = Atomics.xor(ta, 0, 1); + + assertEq(val, 3); + assertEq(ta[0], 2); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Atomics/detached-buffers.js b/js/src/tests/non262/Atomics/detached-buffers.js new file mode 100644 index 0000000000..e3bc269b40 --- /dev/null +++ b/js/src/tests/non262/Atomics/detached-buffers.js @@ -0,0 +1,94 @@ +// |reftest| skip-if(!this.Atomics) + +const intArrayConstructors = [ + Int32Array, + Int16Array, + Int8Array, + Uint32Array, + Uint16Array, + Uint8Array, +]; + +function badValue(ta) { + return { + valueOf() { + detachArrayBuffer(ta.buffer); + return 0; + } + }; +} + +// Atomics.load +for (let TA of intArrayConstructors) { + let ta = new TA(1); + + assertThrowsInstanceOf(() => Atomics.load(ta, badValue(ta)), TypeError); +} + +// Atomics.store +for (let TA of intArrayConstructors) { + let ta = new TA(1); + + assertThrowsInstanceOf(() => Atomics.store(ta, badValue(ta), 0), TypeError); + assertThrowsInstanceOf(() => Atomics.store(ta, 0, badValue(ta)), TypeError); +} + +// Atomics.compareExchange +for (let TA of intArrayConstructors) { + let ta = new TA(1); + + assertThrowsInstanceOf(() => Atomics.compareExchange(ta, badValue(ta), 0, 0), TypeError); + assertThrowsInstanceOf(() => Atomics.compareExchange(ta, 0, badValue(ta), 0), TypeError); + assertThrowsInstanceOf(() => Atomics.compareExchange(ta, 0, 0, badValue(ta)), TypeError); +} + +// Atomics.exchange +for (let TA of intArrayConstructors) { + let ta = new TA(1); + + assertThrowsInstanceOf(() => Atomics.exchange(ta, badValue(ta), 0), TypeError); + assertThrowsInstanceOf(() => Atomics.exchange(ta, 0, badValue(ta)), TypeError); +} + +// Atomics.add +for (let TA of intArrayConstructors) { + let ta = new TA(1); + + assertThrowsInstanceOf(() => Atomics.add(ta, badValue(ta), 0), TypeError); + assertThrowsInstanceOf(() => Atomics.add(ta, 0, badValue(ta)), TypeError); +} + +// Atomics.sub +for (let TA of intArrayConstructors) { + let ta = new TA(1); + + assertThrowsInstanceOf(() => Atomics.sub(ta, badValue(ta), 0), TypeError); + assertThrowsInstanceOf(() => Atomics.sub(ta, 0, badValue(ta)), TypeError); +} + +// Atomics.and +for (let TA of intArrayConstructors) { + let ta = new TA(1); + + assertThrowsInstanceOf(() => Atomics.and(ta, badValue(ta), 0), TypeError); + assertThrowsInstanceOf(() => Atomics.and(ta, 0, badValue(ta)), TypeError); +} + +// Atomics.or +for (let TA of intArrayConstructors) { + let ta = new TA(1); + + assertThrowsInstanceOf(() => Atomics.or(ta, badValue(ta), 0), TypeError); + assertThrowsInstanceOf(() => Atomics.or(ta, 0, badValue(ta)), TypeError); +} + +// Atomics.xor +for (let TA of intArrayConstructors) { + let ta = new TA(1); + + assertThrowsInstanceOf(() => Atomics.xor(ta, badValue(ta), 0), TypeError); + assertThrowsInstanceOf(() => Atomics.xor(ta, 0, badValue(ta)), TypeError); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Atomics/shell.js b/js/src/tests/non262/Atomics/shell.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/BigInt/Number-conversion-rounding.js b/js/src/tests/non262/BigInt/Number-conversion-rounding.js new file mode 100644 index 0000000000..5daf68948d --- /dev/null +++ b/js/src/tests/non262/BigInt/Number-conversion-rounding.js @@ -0,0 +1,244 @@ +// Any copyright is dedicated to the Public Domain. +// https://creativecommons.org/licenses/publicdomain/ + +/** + * Edge-case behavior at Number.MAX_VALUE and beyond til overflow to Infinity. + */ +function maxMagnitudeTests(isNegative) +{ + var sign = isNegative ? -1 : +1; + var signBigInt = isNegative ? -1n : 1n; + + const MAX_VALUE = isNegative ? -Number.MAX_VALUE : +Number.MAX_VALUE; + + // 2**971+2**972+...+2**1022+2**1023 + var maxMagnitudeNumber = 0; + for (let i = 971; i < 1024; i++) + maxMagnitudeNumber += 2**i; + maxMagnitudeNumber *= sign; + assertEq(maxMagnitudeNumber, MAX_VALUE); + + // 2**971+2**972+...+2**1022+2**1023 + var maxMagnitudeNumberAsBigInt = 0n; + for (let i = 971n; i < 1024n; i++) + maxMagnitudeNumberAsBigInt += 2n**i; + maxMagnitudeNumberAsBigInt *= signBigInt; + var expectedMaxMagnitude = isNegative + ? -(2n**1024n) + 2n**971n + : 2n**1024n - 2n**971n; + assertEq(maxMagnitudeNumberAsBigInt, expectedMaxMagnitude); + + // Initial sanity tests. + assertEq(BigInt(maxMagnitudeNumber), maxMagnitudeNumberAsBigInt); + assertEq(maxMagnitudeNumber, Number(maxMagnitudeNumberAsBigInt)); + + // Test conversion of BigInt values above Number.MAX_VALUE. + assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 1n), MAX_VALUE); + assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 2n), MAX_VALUE); + assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 3n), MAX_VALUE); + assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 4n), MAX_VALUE); + assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 5n), MAX_VALUE); + assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 6n), MAX_VALUE); + assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 7n), MAX_VALUE); + assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 8n), MAX_VALUE); + assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 9n), MAX_VALUE); + assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 2n**20n), MAX_VALUE); + assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 2n**400n), MAX_VALUE); + assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 2n**800n), MAX_VALUE); + assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 2n**900n), MAX_VALUE); + assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 2n**969n), MAX_VALUE); + + // For conversion purposes, rounding for values above Number.MAX_VALUE do + // rounding with respect to Number.MAX_VALUE and 2**1024 (which is treated as + // the "even" value -- so if the value to convert lies halfway between those two + // values, 2**1024 is selected). But if 2**1024 is the value that *would* have + // been chosen by this process, Infinity is substituted. + assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * (2n**970n - 1n)), MAX_VALUE); + assertEq(Number(maxMagnitudeNumberAsBigInt + signBigInt * 2n**970n), sign * Infinity); +} +maxMagnitudeTests(false); +maxMagnitudeTests(true); + +/** + * Simple single-Digit on x64, double-Digit on x86 tests. + */ + +assertEq(BigInt(Number(2n**53n - 2n)), 2n**53n - 2n); +assertEq(BigInt(Number(2n**53n - 1n)), 2n**53n - 1n); +assertEq(BigInt(Number(2n**53n)), 2n**53n); +assertEq(BigInt(Number(2n**53n + 1n)), 2n**53n); +assertEq(BigInt(Number(2n**53n + 2n)), 2n**53n + 2n); +assertEq(BigInt(Number(2n**53n + 3n)), 2n**53n + 4n); +assertEq(BigInt(Number(2n**53n + 4n)), 2n**53n + 4n); +assertEq(BigInt(Number(2n**53n + 5n)), 2n**53n + 4n); +assertEq(BigInt(Number(2n**53n + 6n)), 2n**53n + 6n); +assertEq(BigInt(Number(2n**53n + 7n)), 2n**53n + 8n); +assertEq(BigInt(Number(2n**53n + 8n)), 2n**53n + 8n); + +assertEq(BigInt(Number(2n**54n - 4n)), 2n**54n - 4n); +assertEq(BigInt(Number(2n**54n - 3n)), 2n**54n - 4n); +assertEq(BigInt(Number(2n**54n - 2n)), 2n**54n - 2n); +assertEq(BigInt(Number(2n**54n - 1n)), 2n**54n); +assertEq(BigInt(Number(2n**54n)), 2n**54n); +assertEq(BigInt(Number(2n**54n + 1n)), 2n**54n); +assertEq(BigInt(Number(2n**54n + 2n)), 2n**54n); +assertEq(BigInt(Number(2n**54n + 3n)), 2n**54n + 4n); +assertEq(BigInt(Number(2n**54n + 4n)), 2n**54n + 4n); +assertEq(BigInt(Number(2n**54n + 5n)), 2n**54n + 4n); +assertEq(BigInt(Number(2n**54n + 6n)), 2n**54n + 8n); +assertEq(BigInt(Number(2n**54n + 7n)), 2n**54n + 8n); +assertEq(BigInt(Number(2n**54n + 8n)), 2n**54n + 8n); + +assertEq(BigInt(Number(2n**55n - 8n)), 2n**55n - 8n); +assertEq(BigInt(Number(2n**55n - 7n)), 2n**55n - 8n); +assertEq(BigInt(Number(2n**55n - 6n)), 2n**55n - 8n); +assertEq(BigInt(Number(2n**55n - 5n)), 2n**55n - 4n); +assertEq(BigInt(Number(2n**55n - 4n)), 2n**55n - 4n); +assertEq(BigInt(Number(2n**55n - 3n)), 2n**55n - 4n); +assertEq(BigInt(Number(2n**55n - 2n)), 2n**55n); +assertEq(BigInt(Number(2n**55n - 1n)), 2n**55n); +assertEq(BigInt(Number(2n**55n)), 2n**55n); +assertEq(BigInt(Number(2n**55n + 1n)), 2n**55n); +assertEq(BigInt(Number(2n**55n + 2n)), 2n**55n); +assertEq(BigInt(Number(2n**55n + 3n)), 2n**55n); +assertEq(BigInt(Number(2n**55n + 4n)), 2n**55n); +assertEq(BigInt(Number(2n**55n + 5n)), 2n**55n + 8n); +assertEq(BigInt(Number(2n**55n + 6n)), 2n**55n + 8n); +assertEq(BigInt(Number(2n**55n + 7n)), 2n**55n + 8n); +assertEq(BigInt(Number(2n**55n + 8n)), 2n**55n + 8n); +assertEq(BigInt(Number(2n**55n + 9n)), 2n**55n + 8n); +assertEq(BigInt(Number(2n**55n + 10n)), 2n**55n + 8n); +assertEq(BigInt(Number(2n**55n + 11n)), 2n**55n + 8n); +assertEq(BigInt(Number(2n**55n + 12n)), 2n**55n + 16n); +assertEq(BigInt(Number(2n**55n + 13n)), 2n**55n + 16n); +assertEq(BigInt(Number(2n**55n + 14n)), 2n**55n + 16n); +assertEq(BigInt(Number(2n**55n + 15n)), 2n**55n + 16n); +assertEq(BigInt(Number(2n**55n + 16n)), 2n**55n + 16n); + + +/** + * Simple double-Digit on x64, triple-Digit on x86 tests. + */ + +// The tests below that aren't subtracting bits will have no bits in the +// ultimate significand from the most-significant digit (because of the implicit +// one being excluded). +assertEq(BigInt(Number(2n**64n - 2n**11n)), 2n**64n - 2n**11n); +assertEq(BigInt(Number(2n**64n - 2n**11n + 2n**10n - 1n)), 2n**64n - 2n**11n); +assertEq(BigInt(Number(2n**64n - 2n**11n + 2n**10n)), 2n**64n); +assertEq(BigInt(Number(2n**64n - 2n**10n)), 2n**64n); +assertEq(BigInt(Number(2n**64n)), 2n**64n); +assertEq(BigInt(Number(2n**64n + 1n)), 2n**64n); +assertEq(BigInt(Number(2n**64n + 2n**5n)), 2n**64n); +assertEq(BigInt(Number(2n**64n + 2n**10n)), 2n**64n); +assertEq(BigInt(Number(2n**64n + 2n**11n)), 2n**64n); +assertEq(BigInt(Number(2n**64n + 2n**11n + 1n)), 2n**64n + 2n**12n); +assertEq(BigInt(Number(2n**64n + 2n**12n)), 2n**64n + 2n**12n); +assertEq(BigInt(Number(2n**64n + 2n**12n + 1n)), 2n**64n + 2n**12n); +assertEq(BigInt(Number(2n**64n + 2n**12n + 2n**5n)), 2n**64n + 2n**12n); +assertEq(BigInt(Number(2n**64n + 2n**12n + 2n**10n)), 2n**64n + 2n**12n); +assertEq(BigInt(Number(2n**64n + 2n**12n + 2n**11n - 1n)), 2n**64n + 2n**12n); +assertEq(BigInt(Number(2n**64n + 2n**12n + 2n**11n)), 2n**64n + 2n**13n); +assertEq(BigInt(Number(2n**64n + 2n**12n + 2n**11n + 1n)), 2n**64n + 2n**13n); + +// These tests *will* have a bit from the most-significant digit in the ultimate +// significand. +assertEq(BigInt(Number(2n**65n - 2n**12n)), 2n**65n - 2n**12n); +assertEq(BigInt(Number(2n**65n - 2n**12n + 2n**11n - 1n)), 2n**65n - 2n**12n); +assertEq(BigInt(Number(2n**65n - 2n**12n + 2n**11n)), 2n**65n); +assertEq(BigInt(Number(2n**65n - 2n**11n)), 2n**65n); +assertEq(BigInt(Number(2n**65n)), 2n**65n); +assertEq(BigInt(Number(2n**65n + 1n)), 2n**65n); +assertEq(BigInt(Number(2n**65n + 2n**5n)), 2n**65n); +assertEq(BigInt(Number(2n**65n + 2n**11n)), 2n**65n); +assertEq(BigInt(Number(2n**65n + 2n**12n)), 2n**65n); +assertEq(BigInt(Number(2n**65n + 2n**12n + 1n)), 2n**65n + 2n**13n); +assertEq(BigInt(Number(2n**65n + 2n**13n)), 2n**65n + 2n**13n); +assertEq(BigInt(Number(2n**65n + 2n**13n + 1n)), 2n**65n + 2n**13n); +assertEq(BigInt(Number(2n**65n + 2n**13n + 2n**5n)), 2n**65n + 2n**13n); +assertEq(BigInt(Number(2n**65n + 2n**13n + 2n**11n)), 2n**65n + 2n**13n); +assertEq(BigInt(Number(2n**65n + 2n**13n + 2n**12n - 1n)), 2n**65n + 2n**13n); +assertEq(BigInt(Number(2n**65n + 2n**13n + 2n**12n)), 2n**65n + 2n**14n); +assertEq(BigInt(Number(2n**65n + 2n**13n + 2n**12n + 1n)), 2n**65n + 2n**14n); + +// ...and in these tests, the contributed bit from the most-significant digit +// is additionally nonzero. +assertEq(BigInt(Number(2n**65n + 2n**64n)), 2n**65n + 2n**64n); +assertEq(BigInt(Number(2n**65n + 2n**64n + 1n)), 2n**65n + 2n**64n); +assertEq(BigInt(Number(2n**65n + 2n**64n + 2n**5n)), 2n**65n + 2n**64n); +assertEq(BigInt(Number(2n**65n + 2n**64n + 2n**11n)), 2n**65n + 2n**64n); +assertEq(BigInt(Number(2n**65n + 2n**64n + 2n**12n)), 2n**65n + 2n**64n); +assertEq(BigInt(Number(2n**65n + 2n**64n + 2n**12n + 1n)), 2n**65n + 2n**64n + 2n**13n); +assertEq(BigInt(Number(2n**65n + 2n**64n + 2n**13n)), 2n**65n + 2n**64n + 2n**13n); +assertEq(BigInt(Number(2n**65n + 2n**64n + 2n**13n + 1n)), 2n**65n + 2n**64n + 2n**13n); +assertEq(BigInt(Number(2n**65n + 2n**64n + 2n**13n + 2n**5n)), 2n**65n + 2n**64n + 2n**13n); +assertEq(BigInt(Number(2n**65n + 2n**64n + 2n**13n + 2n**11n)), 2n**65n + 2n**64n + 2n**13n); +assertEq(BigInt(Number(2n**65n + 2n**64n + 2n**13n + 2n**12n - 1n)), 2n**65n + 2n**64n + 2n**13n); +assertEq(BigInt(Number(2n**65n + 2n**64n + 2n**13n + 2n**12n)), 2n**65n + 2n**64n + 2n**14n); +assertEq(BigInt(Number(2n**65n + 2n**64n + 2n**13n + 2n**12n + 1n)), 2n**65n + 2n**64n + 2n**14n); + +/** + * Versions of the testing above with all the high-order bits massively bumped + * upward to test that super-low bits, not just bits in high digits, are + * properly accounted for in rounding. + */ + +// The tests below that aren't subtracting bits will have no bits in the +// ultimate significand from the most-significant digit (because of the implicit +// one being excluded). +assertEq(BigInt(Number(2n**940n - 2n**887n + 1n)), 2n**940n - 2n**887n); +assertEq(BigInt(Number(2n**940n - 2n**887n + 2n**886n - 1n)), 2n**940n - 2n**887n); +assertEq(BigInt(Number(2n**940n - 2n**887n + 2n**886n)), 2n**940n); +assertEq(BigInt(Number(2n**940n - 2n**886n)), 2n**940n); +assertEq(BigInt(Number(2n**940n)), 2n**940n); +assertEq(BigInt(Number(2n**940n + 1n)), 2n**940n); +assertEq(BigInt(Number(2n**940n + 2n**880n)), 2n**940n); +assertEq(BigInt(Number(2n**940n + 2n**885n)), 2n**940n); +assertEq(BigInt(Number(2n**940n + 2n**887n)), 2n**940n); +assertEq(BigInt(Number(2n**940n + 2n**887n + 1n)), 2n**940n + 2n**888n); +assertEq(BigInt(Number(2n**940n + 2n**888n)), 2n**940n + 2n**888n); +assertEq(BigInt(Number(2n**940n + 2n**888n + 1n)), 2n**940n + 2n**888n); +assertEq(BigInt(Number(2n**940n + 2n**888n + 2n**5n)), 2n**940n + 2n**888n); +assertEq(BigInt(Number(2n**940n + 2n**888n + 2n**12n)), 2n**940n + 2n**888n); +assertEq(BigInt(Number(2n**940n + 2n**888n + 2n**887n - 1n)), 2n**940n + 2n**888n); +assertEq(BigInt(Number(2n**940n + 2n**888n + 2n**887n)), 2n**940n + 2n**889n); +assertEq(BigInt(Number(2n**940n + 2n**888n + 2n**887n + 1n)), 2n**940n + 2n**889n); + +// These tests *will* have a bit from the most-significant digit in the ultimate +// significand. +assertEq(BigInt(Number(2n**941n - 2n**888n)), 2n**941n - 2n**888n); +assertEq(BigInt(Number(2n**941n - 2n**888n + 2n**887n - 1n)), 2n**941n - 2n**888n); +assertEq(BigInt(Number(2n**941n - 2n**888n + 2n**887n)), 2n**941n); +assertEq(BigInt(Number(2n**941n - 2n**887n)), 2n**941n); +assertEq(BigInt(Number(2n**941n)), 2n**941n); +assertEq(BigInt(Number(2n**941n + 1n)), 2n**941n); +assertEq(BigInt(Number(2n**941n + 2n**881n)), 2n**941n); +assertEq(BigInt(Number(2n**941n + 2n**886n)), 2n**941n); +assertEq(BigInt(Number(2n**941n + 2n**888n)), 2n**941n); +assertEq(BigInt(Number(2n**941n + 2n**888n + 1n)), 2n**941n + 2n**889n); +assertEq(BigInt(Number(2n**941n + 2n**889n)), 2n**941n + 2n**889n); +assertEq(BigInt(Number(2n**941n + 2n**889n + 1n)), 2n**941n + 2n**889n); +assertEq(BigInt(Number(2n**941n + 2n**889n + 2n**5n)), 2n**941n + 2n**889n); +assertEq(BigInt(Number(2n**941n + 2n**889n + 2n**12n)), 2n**941n + 2n**889n); +assertEq(BigInt(Number(2n**941n + 2n**889n + 2n**888n - 1n)), 2n**941n + 2n**889n); +assertEq(BigInt(Number(2n**941n + 2n**889n + 2n**888n)), 2n**941n + 2n**890n); +assertEq(BigInt(Number(2n**941n + 2n**889n + 2n**888n + 1n)), 2n**941n + 2n**890n); + +// ...and in these tests, the contributed bit from the most-significant digit +// is additionally nonzero. +assertEq(BigInt(Number(2n**941n + 2n**940n)), 2n**941n + 2n**940n); +assertEq(BigInt(Number(2n**941n + 2n**940n + 1n)), 2n**941n + 2n**940n); +assertEq(BigInt(Number(2n**941n + 2n**940n + 2n**881n)), 2n**941n + 2n**940n); +assertEq(BigInt(Number(2n**941n + 2n**940n + 2n**886n)), 2n**941n + 2n**940n); +assertEq(BigInt(Number(2n**941n + 2n**940n + 2n**888n)), 2n**941n + 2n**940n); +assertEq(BigInt(Number(2n**941n + 2n**940n + 2n**888n + 1n)), 2n**941n + 2n**940n + 2n**889n); +assertEq(BigInt(Number(2n**941n + 2n**940n + 2n**889n)), 2n**941n + 2n**940n + 2n**889n); +assertEq(BigInt(Number(2n**941n + 2n**940n + 2n**889n + 1n)), 2n**941n + 2n**940n + 2n**889n); +assertEq(BigInt(Number(2n**941n + 2n**940n + 2n**889n + 2n**5n)), 2n**941n + 2n**940n + 2n**889n); +assertEq(BigInt(Number(2n**941n + 2n**940n + 2n**889n + 2n**12n)), 2n**941n + 2n**940n + 2n**889n); +assertEq(BigInt(Number(2n**941n + 2n**940n + 2n**889n + 2n**888n - 1n)), 2n**941n + 2n**940n + 2n**889n); +assertEq(BigInt(Number(2n**941n + 2n**940n + 2n**889n + 2n**888n)), 2n**941n + 2n**940n + 2n**890n); +assertEq(BigInt(Number(2n**941n + 2n**940n + 2n**889n + 2n**888n + 1n)), 2n**941n + 2n**940n + 2n**890n); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/BigInt/decimal.js b/js/src/tests/non262/BigInt/decimal.js new file mode 100644 index 0000000000..f461307744 --- /dev/null +++ b/js/src/tests/non262/BigInt/decimal.js @@ -0,0 +1,30 @@ +// Any copyright is dedicated to the Public Domain. +// https://creativecommons.org/licenses/publicdomain/ + +// Check base-10 BigInt string conversion +const decimalTests = [ + [32n, -1n, 1n, "4294967295"], + [32n, -1n, -1n, "-4294967295"], + [32n, 0n, 1n, "4294967296"], + [32n, 0n, -1n, "-4294967296"], + [32n, 1n, 1n, "4294967297"], + [32n, 1n, -1n, "-4294967297"], + [64n, -1n, 1n, "18446744073709551615"], + [64n, -1n, -1n, "-18446744073709551615"], + [64n, 0n, 1n, "18446744073709551616"], + [64n, 0n, -1n, "-18446744073709551616"], + [64n, 1n, 1n, "18446744073709551617"], + [64n, 1n, -1n, "-18446744073709551617"], + [128n, -1n, 1n, "340282366920938463463374607431768211455"], + [128n, -1n, -1n, "-340282366920938463463374607431768211455"], + [128n, 0n, 1n, "340282366920938463463374607431768211456"], + [128n, 0n, -1n, "-340282366920938463463374607431768211456"], + [128n, 1n, 1n, "340282366920938463463374607431768211457"], + [128n, 1n, -1n, "-340282366920938463463374607431768211457"], +]; +for (const [power, offset, sign, result] of decimalTests) { + assertEq(((2n**power+offset)*sign).toString(), + result); +} + +reportCompare(true, true); diff --git a/js/src/tests/non262/BigInt/large-bit-length.js b/js/src/tests/non262/BigInt/large-bit-length.js new file mode 100644 index 0000000000..5f4617159b --- /dev/null +++ b/js/src/tests/non262/BigInt/large-bit-length.js @@ -0,0 +1,33 @@ +// Any copyright is dedicated to the Public Domain. +// https://creativecommons.org/licenses/publicdomain/ + +function test(thunk, result) { + let val, err; + try { + val = thunk(); + } catch (e) { + err = e; + } + if (err) { + assertEq(err instanceof RangeError, true); + } else { + assertEq(val, result); + } +} + +const UINT32_MAX = 2**32-1; + +// Check that BigInt.asIntN and BigInt.asUintN either return correct results or +// throw RangeErrors for large |bits| arguments. GMP uses a type equivalent to +// 'unsigned long' for bit counts, which may be too small to represent all JS +// integer indexes. +for (let bits of [UINT32_MAX-1, UINT32_MAX, UINT32_MAX+1, Number.MAX_SAFE_INTEGER]) { + test(() => BigInt.asIntN(bits, 1n), 1n); + test(() => BigInt.asIntN(bits, 0n), 0n); + test(() => BigInt.asIntN(bits, -1n), -1n); + test(() => BigInt.asUintN(bits, 1n), 1n); + test(() => BigInt.asUintN(bits, 0n), 0n); + // Skip testing asUintN with negative BigInts since it could OOM. +} + +reportCompare(true, true); diff --git a/js/src/tests/non262/BigInt/mod.js b/js/src/tests/non262/BigInt/mod.js new file mode 100644 index 0000000000..2d7bde0462 --- /dev/null +++ b/js/src/tests/non262/BigInt/mod.js @@ -0,0 +1,8 @@ +// Any copyright is dedicated to the Public Domain. +// https://creativecommons.org/licenses/publicdomain/ + +// Check that |x % x| returns zero when |x| contains multiple digits +assertEq(0x10000000000000000n % 0x10000000000000000n, 0n); +assertEq(-0x10000000000000000n % -0x10000000000000000n, 0n); + +reportCompare(true, true); diff --git a/js/src/tests/non262/BigInt/property-name-guessed-name.js b/js/src/tests/non262/BigInt/property-name-guessed-name.js new file mode 100644 index 0000000000..feb91345b2 --- /dev/null +++ b/js/src/tests/non262/BigInt/property-name-guessed-name.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!xulRuntime.shell) + +// BigInts currently don't participate when computing guessed function names. + +var p = {}; +p[1] = function(){}; +p[2n] = function(){}; + +assertEq(displayName(p[1]), "p[1]"); +assertEq(displayName(p[2]), ""); + +var q = { + 1: [function(){}], + 2n: [function(){}], +}; + +assertEq(displayName(q[1][0]), "q[1]<"); +assertEq(displayName(q[2][0]), "q<"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/BigInt/property-name.js b/js/src/tests/non262/BigInt/property-name.js new file mode 100644 index 0000000000..85addd550a --- /dev/null +++ b/js/src/tests/non262/BigInt/property-name.js @@ -0,0 +1,194 @@ +// BigInt literals as property keys. +{ + let o = { + 0n: "0", + 1n: "1", + + // 2**31 + 2147483647n: "2^31-1", + 2147483648n: "2^31", + 2147483649n: "2^31+1", + + // 2**32 + 4294967295n: "2^32-1", + 4294967296n: "2^32", + 4294967297n: "2^32+1", + + // 2n**63n + 9223372036854775807n: "2^63-1", + 9223372036854775808n: "2^63", + 9223372036854775809n: "2^63+1", + + // 2n**64n + 18446744073709551615n: "2^64-1", + 18446744073709551616n: "2^64", + 18446744073709551617n: "2^64+1", + }; + + assertEq(o[0], "0"); + assertEq(o[1], "1"); + + assertEq(o[2147483647], "2^31-1"); + assertEq(o[2147483648], "2^31"); + assertEq(o[2147483649], "2^31+1"); + + assertEq(o[4294967295], "2^32-1"); + assertEq(o[4294967296], "2^32"); + assertEq(o[4294967297], "2^32+1"); + + assertEq(o["9223372036854775807"], "2^63-1"); + assertEq(o["9223372036854775808"], "2^63"); + assertEq(o["9223372036854775809"], "2^63+1"); + + assertEq(o["18446744073709551615"], "2^64-1"); + assertEq(o["18446744073709551616"], "2^64"); + assertEq(o["18446744073709551617"], "2^64+1"); +} + +// With non-decimal different base. +{ + let o = { + 0b1n: "1", + 0o2n: "2", + 0x3n: "3", + }; + + assertEq(o[1], "1"); + assertEq(o[2], "2"); + assertEq(o[3], "3"); +} + +// With numeric separators. +{ + let o = { + 1_2_3n: "123", + }; + + assertEq(o[123], "123"); +} + +// BigInt literals as method property names. +{ + let o = { + 1n() {}, + *2n() {}, + async 3n() {}, + async* 4n() {}, + get 5n() {}, + set 6n(x) {}, + }; + + assertEqArray(Object.getOwnPropertyNames(o), [ + "1", "2", "3", "4", "5", "6", + ]); + + assertEq(o[1].name, "1"); + assertEq(o[2].name, "2"); + assertEq(o[3].name, "3"); + assertEq(o[4].name, "4"); + assertEq(Object.getOwnPropertyDescriptor(o, 5).get.name, "get 5"); + assertEq(Object.getOwnPropertyDescriptor(o, 6).set.name, "set 6"); +} + +// BigInt literals as class method property names. +{ + class C { + 1n() {} + *2n() {} + async 3n() {} + async* 4n() {} + get 5n() {} + set 6n(x) {} + } + let o = C.prototype; + + assertEqArray(Object.getOwnPropertyNames(o), [ + "1", "2", "3", "4", "5", "6", + "constructor", + ]); + + assertEq(o[1].name, "1"); + assertEq(o[2].name, "2"); + assertEq(o[3].name, "3"); + assertEq(o[4].name, "4"); + assertEq(Object.getOwnPropertyDescriptor(o, 5).get.name, "get 5"); + assertEq(Object.getOwnPropertyDescriptor(o, 6).set.name, "set 6"); +} + +// BigInt literals as static class method property names. +{ + class C { + static 1n() {} + static *2n() {} + static async 3n() {} + static async* 4n() {} + static get 5n() {} + static set 6n(x) {} + } + let o = C; + + // NB: Sort names because lazily resolved "length" and "name" properties are + // inserted in the wrong order. + assertEqArray(Object.getOwnPropertyNames(o).sort(), [ + "1", "2", "3", "4", "5", "6", + "length", "name", "prototype", + ]); + + assertEq(o[1].name, "1"); + assertEq(o[2].name, "2"); + assertEq(o[3].name, "3"); + assertEq(o[4].name, "4"); + assertEq(Object.getOwnPropertyDescriptor(o, 5).get.name, "get 5"); + assertEq(Object.getOwnPropertyDescriptor(o, 6).set.name, "set 6"); +} + +// BigInt literals as class field property names. +{ + let o = new class { + 1n; + 2n = "ok"; + }; + + assertEq(o[1], undefined); + assertEq(o[2], "ok"); +} + +// In binding destructuring contexts. +{ + let {0n: a} = ["ok"]; + assertEq(a, "ok"); +} + +// In binding destructuring contexts with object rest pattern. +{ + let {0n: a, ...b} = ["ok", "test"]; + assertEq(a, "ok"); + assertEqArray(Object.getOwnPropertyNames(b), ["1"]); +} + +// In assignment destructuring contexts. +{ + let a; + ({0n: a} = ["ok"]); + assertEq(a, "ok"); +} + +// In assignment destructuring contexts with object rest pattern. +{ + let a, b; + ({0n: a, ...b} = ["ok", "test"]); + assertEq(a, "ok"); + assertEqArray(Object.getOwnPropertyNames(b), ["1"]); +} + +// BigInt literals as inferred names. +{ + let o = { + 0xan: function(){}, + }; + + assertEq(o[10].name, "10"); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Boolean/15.6.4.2.js b/js/src/tests/non262/Boolean/15.6.4.2.js new file mode 100644 index 0000000000..3e10afa388 --- /dev/null +++ b/js/src/tests/non262/Boolean/15.6.4.2.js @@ -0,0 +1,17 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +assertEq(raisesException(TypeError)('Boolean.prototype.toString.call(42)'), true); +assertEq(raisesException(TypeError)('Boolean.prototype.toString.call("")'), true); +assertEq(raisesException(TypeError)('Boolean.prototype.toString.call({})'), true); +assertEq(raisesException(TypeError)('Boolean.prototype.toString.call(null)'), true); +assertEq(raisesException(TypeError)('Boolean.prototype.toString.call([])'), true); +assertEq(raisesException(TypeError)('Boolean.prototype.toString.call(undefined)'), true); +assertEq(raisesException(TypeError)('Boolean.prototype.toString.call(new String())'), true); + +assertEq(completesNormally('Boolean.prototype.toString.call(true)'), true); +assertEq(completesNormally('Boolean.prototype.toString.call(new Boolean(true))'), true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/Boolean/browser.js b/js/src/tests/non262/Boolean/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Boolean/no-boolean-toJSON.js b/js/src/tests/non262/Boolean/no-boolean-toJSON.js new file mode 100644 index 0000000000..e12c8049b0 --- /dev/null +++ b/js/src/tests/non262/Boolean/no-boolean-toJSON.js @@ -0,0 +1,17 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Author: Tom Schuster + */ + +JSON.stringify(new Boolean(false), function(k, v) { + assertEq(typeof v, "object"); +}); + +assertEq(Boolean.prototype.hasOwnProperty('toJSON'), false); + +Object.prototype.toJSON = function() { return 2; }; +assertEq(JSON.stringify(new Boolean(true)), "2"); + +if (typeof reportCompare === 'function') + reportCompare(true, true); diff --git a/js/src/tests/non262/Boolean/shell.js b/js/src/tests/non262/Boolean/shell.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/DataView/browser.js b/js/src/tests/non262/DataView/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/DataView/detach-after-construction.js b/js/src/tests/non262/DataView/detach-after-construction.js new file mode 100644 index 0000000000..e767fcffae --- /dev/null +++ b/js/src/tests/non262/DataView/detach-after-construction.js @@ -0,0 +1,9 @@ +var buf = new ArrayBuffer([1,2]); +var bufView = new DataView(buf); + +detachArrayBuffer(buf); + +assertThrowsInstanceOf(() => bufView.getInt8(0), TypeError); + +if (typeof reportCompare === 'function') + reportCompare(0, 0, "OK"); diff --git a/js/src/tests/non262/DataView/get-set-index-range.js b/js/src/tests/non262/DataView/get-set-index-range.js new file mode 100644 index 0000000000..4391591b67 --- /dev/null +++ b/js/src/tests/non262/DataView/get-set-index-range.js @@ -0,0 +1,36 @@ +var buffer = new ArrayBuffer(2); +var view = new DataView(buffer); + +function check(view) { + for (let fun of ['getInt8', 'setInt8', 'getInt16', 'setInt16']) { + assertThrowsInstanceOf(() => view[fun](-10), RangeError); + assertThrowsInstanceOf(() => view[fun](-Infinity), RangeError); + assertThrowsInstanceOf(() => view[fun](Infinity), RangeError); + + assertThrowsInstanceOf(() => view[fun](Math.pow(2, 53)), RangeError); + assertThrowsInstanceOf(() => view[fun](Math.pow(2, 54)), RangeError); + } +} + +check(view); + +for (let fun of ['getInt8', 'getInt16']) { + assertEq(view[fun](0), 0); + assertEq(view[fun](undefined), 0); + assertEq(view[fun](NaN), 0); +} + +if ('detachArrayBuffer' in this) { + // ToIndex is called before detachment check, so we can tell the difference + // between a ToIndex failure and a real out of bounds failure. + detachArrayBuffer(buffer); + + check(view); + + assertThrowsInstanceOf(() => view.getInt8(0), TypeError); + assertThrowsInstanceOf(() => view.setInt8(0, 0), TypeError); + assertThrowsInstanceOf(() => view.getInt8(Math.pow(2, 53) - 1), TypeError); + assertThrowsInstanceOf(() => view.setInt8(Math.pow(2, 53) - 1, 0), TypeError); +} + +reportCompare(0, 0, 'OK'); diff --git a/js/src/tests/non262/DataView/getter-name.js b/js/src/tests/non262/DataView/getter-name.js new file mode 100644 index 0000000000..600b7da8b3 --- /dev/null +++ b/js/src/tests/non262/DataView/getter-name.js @@ -0,0 +1,11 @@ +var BUGNUMBER = 1180290; +var summary = 'DataView getters should have get prefix'; + +print(BUGNUMBER + ": " + summary); + +assertEq(Object.getOwnPropertyDescriptor(DataView.prototype, "buffer").get.name, "get buffer"); +assertEq(Object.getOwnPropertyDescriptor(DataView.prototype, "byteLength").get.name, "get byteLength"); +assertEq(Object.getOwnPropertyDescriptor(DataView.prototype, "byteOffset").get.name, "get byteOffset"); + +if (typeof reportCompare === 'function') + reportCompare(true, true); diff --git a/js/src/tests/non262/DataView/shell.js b/js/src/tests/non262/DataView/shell.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Date/15.9.4.2.js b/js/src/tests/non262/Date/15.9.4.2.js new file mode 100644 index 0000000000..7100f927f1 --- /dev/null +++ b/js/src/tests/non262/Date/15.9.4.2.js @@ -0,0 +1,134 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 430930; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function iso(d) +{ + return new Date(d).toISOString(); +} + +function check(s, millis){ + description = "Date.parse('"+s+"') == '"+iso(millis)+"'"; + expected = millis; + actual = Date.parse(s); + reportCompare(expected, actual, description); +} + +function checkInvalid(s) +{ + description = "Date.parse('"+s+"') produces invalid date"; + expected = NaN; + actual = Date.parse(s); + reportCompare(expected, actual, description); +} + +function dd(year, month, day, hour, minute, second, millis){ + return Date.UTC(year, month-1, day, hour, minute, second, millis); +} + +function TZAtDate(d){ + return d.getTimezoneOffset() * 60000; +} + +function TZInMonth(month, year){ + return TZAtDate(new Date(dd(year,month,1,0,0,0,0))); +} + +function test() +{ + printBugNumber(BUGNUMBER); + + Jan1970TZ = TZInMonth(1, 1970); + Jan2009TZ = TZInMonth(1, 2009); + Jul2009TZ = TZInMonth(7, 2009); + CurrTZ = TZAtDate(new Date()); + + // formats with explicit timezone + check("2009-07-23T19:53:21.001+12:00", dd(2009,7,23,7,53,21,1)); + check("2009-07-23T19:53:21+12:00", dd(2009,7,23,7,53,21,0)); + check("2009-07-23T19:53+12:00", dd(2009,7,23,7,53,0,0)); + + check("2009-07T19:53:21.001+12:00", dd(2009,7,1,7,53,21,1)); + check("2009-07T19:53:21+12:00", dd(2009,7,1,7,53,21,0)); + check("2009-07T19:53+12:00", dd(2009,7,1,7,53,0,0)); + + check("2009T19:53:21.001+12:00", dd(2009,1,1,7,53,21,1)); + check("2009T19:53:21+12:00", dd(2009,1,1,7,53,21,0)); + check("2009T19:53+12:00", dd(2009,1,1,7,53,0,0)); + + checkInvalid("T19:53:21.001+12:00"); + checkInvalid("T19:53:21+12:00"); + checkInvalid("T19:53+12:00"); + + // formats without timezone uses the timezone as at that date + check("2009-07-23T19:53:21.001", dd(2009,7,23,19,53,21,1)+Jul2009TZ); + check("2009-07-23T19:53:21", dd(2009,7,23,19,53,21,0)+Jul2009TZ); + check("2009-07-23T19:53", dd(2009,7,23,19,53,0,0)+Jul2009TZ); + + check("2009-07T19:53:21.001", dd(2009,7,1,19,53,21,1)+Jul2009TZ); + check("2009-07T19:53:21", dd(2009,7,1,19,53,21,0)+Jul2009TZ); + check("2009-07T19:53", dd(2009,7,1,19,53,0,0)+Jul2009TZ); + + check("2009T19:53:21.001", dd(2009,1,1,19,53,21,1)+Jan2009TZ); + check("2009T19:53:21", dd(2009,1,1,19,53,21,0)+Jan2009TZ); + check("2009T19:53", dd(2009,1,1,19,53,0,0)+Jan2009TZ); + + checkInvalid("T19:53:21.001"); + checkInvalid("T19:53:21"); + checkInvalid("T19:53"); + + // with no time at all assume UTC + check("2009-07-23", dd(2009,7,23,0,0,0,0)); + check("2009-07", dd(2009,7,1,0,0,0,0)); + check("2009", dd(2009,1,1,0,0,0,0)); + + // one field too big + checkInvalid("2009-13-23T19:53:21.001+12:00"); + checkInvalid("2009-07-32T19:53:21.001+12:00"); + checkInvalid("2009-07-23T25:53:21.001+12:00"); + checkInvalid("2009-07-23T19:60:21.001+12:00"); + checkInvalid("2009-07-23T19:53:60.001+12:00"); + checkInvalid("2009-07-23T19:53:21.001+24:00"); + checkInvalid("2009-07-23T19:53:21.001+12:60"); + + // other month ends + check("2009-06-30T19:53:21.001+12:00", dd(2009,6,30,7,53,21,1)); + check("2009-06-31T19:53:21.001+12:00", dd(2009,7,1,7,53,21,1)); + check("2009-02-28T19:53:21.001+12:00", dd(2009,2,28,7,53,21,1)); + check("2009-02-29T19:53:21.001+12:00", dd(2009,3,1,7,53,21,1)); + check("2008-02-29T19:53:21.001+12:00", dd(2008,2,29,7,53,21,1)); + check("2008-02-30T19:53:21.001+12:00", dd(2008,3,1,7,53,21,1)); + + // limits of representation + checkInvalid("-271821-04-19T23:59:59.999Z"); + check("-271821-04-20", -8.64e15); + check("+275760-09-13", 8.64e15); + checkInvalid("+275760-09-13T00:00:00.001Z"); + + check("-269845-07-23T19:53:21.001+12:00", dd(-269845,7,23,7,53,21,1)); + check("+273785-07-23T19:53:21.001+12:00", dd(273785,7,23,7,53,21,1)); + + // explicit UTC + check("2009-07-23T19:53:21.001Z", dd(2009,7,23,19,53,21,1)); + check("+002009-07-23T19:53:21.001Z", dd(2009,7,23,19,53,21,1)); + + // different timezones + check("2009-07-23T19:53:21.001+12:00", dd(2009,7,23,7,53,21,1)); + check("2009-07-23T00:53:21.001-07:00", dd(2009,7,23,7,53,21,1)); + + // 00:00 and 24:00 + check("2009-07-23T00:00:00.000-07:00", dd(2009,7,23,7,0,0,0)); + check("2009-07-23T24:00:00.000-07:00", dd(2009,7,24,7,0,0,0)); + + // Bug 730838 - non-zero fraction part for midnight should produce NaN + checkInvalid("1970-01-01T24:00:00.500Z"); +} diff --git a/js/src/tests/non262/Date/15.9.5.5-02.js b/js/src/tests/non262/Date/15.9.5.5-02.js new file mode 100644 index 0000000000..07623e675c --- /dev/null +++ b/js/src/tests/non262/Date/15.9.5.5-02.js @@ -0,0 +1,63 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 398485; +var summary = 'Date.prototype.toLocaleString should not clamp year'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + var d; + var y; + var l; + var maxms = 8640000000000000; + + d = new Date(-maxms ); + y = d.getFullYear(); + + actual = y; + expect = -271821; + reportCompare(expect, actual, summary + ': check year'); + + l = d.toLocaleString(); + print(l); + if (this.hasOwnProperty("Intl")) { + // ECMA-402 specifies that toLocaleString uses a proleptic Gregorian + // calender without year 0. + // Also, localized strings usually use era indicators such as "BC" + // instead of minus signs. + expect = Math.abs(y - 1) + ''; + } else { + // ECMA-262 up to edition 5.1 didn't specify toLocaleString; + // the previous implementation assumed a calendar with year 0 and used + // minus sign. + expect = y + ''; + } + actual = l.match(/-?[0-9]{3,}/) + ''; + reportCompare(expect, actual, summary + ': check toLocaleString'); + + d = new Date(maxms ); + y = d.getFullYear(); + l = d.toLocaleString(); + print(l); + + actual = y; + expect = 275760; + reportCompare(expect, actual, summary + ': check year'); + + actual = l.match(new RegExp(y)) + ''; + expect = y + ''; + reportCompare(expect, actual, summary + ': check toLocaleString'); +} diff --git a/js/src/tests/non262/Date/15.9.5.5.js b/js/src/tests/non262/Date/15.9.5.5.js new file mode 100644 index 0000000000..1a21b33a63 --- /dev/null +++ b/js/src/tests/non262/Date/15.9.5.5.js @@ -0,0 +1,111 @@ +// |reftest| random-if(xulRuntime.OS=="Linux") +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + File Name: 15.9.5.5.js + ECMA Section: 15.9.5.5 Date.prototype.toLocaleString() + Description: + This function returns a string value. The contents of the string are + implementation dependent, but are intended to represent the "date" + portion of the Date in the current time zone in a convenient, + human-readable form. We can't test the content of the string, + but can verify that the string is parsable by Date.parse + + The toLocaleString function is not generic; it generates a runtime error + if its 'this' value is not a Date object. Therefore it cannot be transferred + to other kinds of objects for use as a method. + + Note: This test isn't supposed to work with a non-English locale per spec. + + Author: pschwartau@netscape.com + Date: 14 november 2000 +*/ + +var SECTION = "15.9.5.5"; +var TITLE = "Date.prototype.toLocaleString()"; + +var status = ''; +var actual = ''; +var expect = ''; + + +writeHeaderToLog( SECTION + " "+ TITLE); + +var now = new Date(); + +// first, some generic tests - + +status = "typeof (now.toLocaleString())"; +actual = typeof (now.toLocaleString()); +expect = "string"; +addTestCase(); + +status = "Date.prototype.toLocaleString.length"; +actual = Date.prototype.toLocaleString.length; +expect = 0; +addTestCase(); + +// Date.parse is accurate to the second; valueOf() to the millisecond - +status = "Math.abs(Date.parse(now.toLocaleString('en-US')) - now.valueOf()) < 1000"; +actual = Math.abs(Date.parse(now.toLocaleString('en-US')) - now.valueOf()) < 1000; +expect = true; +addTestCase(); + + + +// 1970 +addDateTestCase(0); +addDateTestCase(TZ_ADJUST); + + +// 1900 +addDateTestCase(UTC_01_JAN_1900); +addDateTestCase(UTC_01_JAN_1900 -TZ_ADJUST); + + +// 2000 +addDateTestCase(UTC_01_JAN_2000); +addDateTestCase(UTC_01_JAN_2000 -TZ_ADJUST); + + +// 29 Feb 2000 +addDateTestCase(UTC_29_FEB_2000); +addDateTestCase(UTC_29_FEB_2000 - 1000); +addDateTestCase(UTC_29_FEB_2000 - TZ_ADJUST); + + +// 2005 +addDateTestCase(UTC_01_JAN_2005); +addDateTestCase(UTC_01_JAN_2005 - 1000); +addDateTestCase(UTC_01_JAN_2005-TZ_ADJUST); + + + +//----------------------------------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------------------------------- + + +function addTestCase() +{ + AddTestCase( + status, + expect, + actual); +} + + +function addDateTestCase(date_given_in_milliseconds) +{ + var givenDate = new Date(date_given_in_milliseconds); + + status = 'Date.parse(' + givenDate + ').toLocaleString("en-US"))'; + actual = Date.parse(givenDate.toLocaleString("en-US")); + expect = date_given_in_milliseconds; + addTestCase(); +} + diff --git a/js/src/tests/non262/Date/15.9.5.6.js b/js/src/tests/non262/Date/15.9.5.6.js new file mode 100644 index 0000000000..67e67630ec --- /dev/null +++ b/js/src/tests/non262/Date/15.9.5.6.js @@ -0,0 +1,118 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + File Name: 15.9.5.6.js + ECMA Section: 15.9.5.6 Date.prototype.toLocaleDateString() + Description: + This function returns a string value. The contents of the string are + implementation dependent, but are intended to represent the "date" + portion of the Date in the current time zone in a convenient, + human-readable form. We can't test the content of the string, + but can verify that the string is parsable by Date.parse + + The toLocaleDateString function is not generic; it generates a runtime error + if its 'this' value is not a Date object. Therefore it cannot be transferred + to other kinds of objects for use as a method. + + Note: This test isn't supposed to work with a non-English locale per spec. + + Author: pschwartau@netscape.com + Date: 14 november 2000 +*/ + +var SECTION = "15.9.5.6"; +var TITLE = "Date.prototype.toLocaleDateString()"; + +var status = ''; +var actual = ''; +var expect = ''; + + +writeHeaderToLog( SECTION + " "+ TITLE); + +var now = new Date(); + +// first, some generic tests - + +status = "typeof (now.toLocaleDateString())"; +actual = typeof (now.toLocaleDateString()); +expect = "string"; +addTestCase(); + +status = "Date.prototype.toLocaleDateString.length"; +actual = Date.prototype.toLocaleDateString.length; +expect = 0; +addTestCase(); + +/* Date.parse is accurate to the second; valueOf() to the millisecond. + Here we expect them to coincide, as we expect a time of exactly midnight - */ +status = "(Date.parse(now.toLocaleDateString('en-US')) - (midnight(now)).valueOf()) == 0"; +actual = (Date.parse(now.toLocaleDateString('en-US')) - (midnight(now)).valueOf()) == 0; +expect = true; +addTestCase(); + + + +// 1970 +addDateTestCase(0); +addDateTestCase(TZ_ADJUST); + + +// 1900 +addDateTestCase(UTC_01_JAN_1900); +addDateTestCase(UTC_01_JAN_1900 - TZ_ADJUST); + + +// 2000 +addDateTestCase(UTC_01_JAN_2000); +addDateTestCase(UTC_01_JAN_2000 - TZ_ADJUST); + + +// 29 Feb 2000 +addDateTestCase(UTC_29_FEB_2000); +addDateTestCase(UTC_29_FEB_2000 - 1000); +addDateTestCase(UTC_29_FEB_2000 - TZ_ADJUST); + + +// 2005 +addDateTestCase(UTC_01_JAN_2005); +addDateTestCase(UTC_01_JAN_2005 - 1000); +addDateTestCase(UTC_01_JAN_2005 - TZ_ADJUST); + + + +//----------------------------------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------------------------------- + + +function addTestCase() +{ + new TestCase( + status, + expect, + actual); +} + + +function addDateTestCase(date_given_in_milliseconds) +{ + var givenDate = new Date(date_given_in_milliseconds); + + status = 'Date.parse(' + givenDate + ').toLocaleDateString("en-US"))'; + actual = Date.parse(givenDate.toLocaleDateString("en-US")); + expect = Date.parse(midnight(givenDate)); + addTestCase(); +} + + +function midnight(givenDate) +{ + // midnight on the given date - + return new Date(givenDate.getFullYear(), givenDate.getMonth(), givenDate.getDate()); +} + diff --git a/js/src/tests/non262/Date/15.9.5.7.js b/js/src/tests/non262/Date/15.9.5.7.js new file mode 100644 index 0000000000..0ce2df9a26 --- /dev/null +++ b/js/src/tests/non262/Date/15.9.5.7.js @@ -0,0 +1,110 @@ +// |reftest| skip-if(xulRuntime.OS=="WINNT") -- Windows doesn't accept IANA names for the TZ env variable +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + File Name: 15.9.5.7.js + ECMA Section: 15.9.5.7 Date.prototype.toLocaleTimeString() + Description: + This function returns a string value. The contents of the string are + implementation dependent, but are intended to represent the "time" + portion of the Date in the current time zone in a convenient, + human-readable form. We test the content of the string by checking + that + + new Date(d.toDateString() + " " + d.toLocaleTimeString()) == d + + Author: pschwartau@netscape.com + Date: 14 november 2000 + Revised: 07 january 2002 because of a change in JS Date format: + Revised: 21 November 2005 since the string comparison stuff is horked. + bclary + + See http://bugzilla.mozilla.org/show_bug.cgi?id=118266 (SpiderMonkey) + See http://bugzilla.mozilla.org/show_bug.cgi?id=118636 (Rhino) +*/ + +var SECTION = "15.9.5.7"; +var TITLE = "Date.prototype.toLocaleTimeString()"; + +var status = ''; +var actual = ''; +var expect = ''; +var givenDate; +var year = ''; +var regexp = ''; +var TimeString = ''; +var reducedDateString = ''; +var hopeThisIsLocaleTimeString = ''; +var cnERR = 'OOPS! FATAL ERROR: no regexp match in extractLocaleTimeString()'; + +writeHeaderToLog(SECTION + " " + TITLE); + +inTimeZone("PST", () => { + var now = new Date(); + + // valueOf() is to accurate to the millisecond, + // Date.parse() is accurate only to the second + var TIME_NOW = now.valueOf(); + + // first, a couple generic tests - + + status = "typeof (now.toLocaleTimeString())"; + actual = typeof (now.toLocaleTimeString()); + expect = "string"; + addTestCase(); + + status = "Date.prototype.toLocaleTimeString.length"; + actual = Date.prototype.toLocaleTimeString.length; + expect = 0; + addTestCase(); + + // 1970 + addDateTestCase(0); + addDateTestCase(TZ_ADJUST); + + // 1900 + addDateTestCase(UTC_01_JAN_1900); + addDateTestCase(UTC_01_JAN_1900 - TZ_ADJUST); + + // 2000 + addDateTestCase(UTC_01_JAN_2000); + addDateTestCase(UTC_01_JAN_2000 - TZ_ADJUST); + + // 29 Feb 2000 + addDateTestCase(UTC_29_FEB_2000); + addDateTestCase(UTC_29_FEB_2000 - 1000); + addDateTestCase(UTC_29_FEB_2000 - TZ_ADJUST); + + // Now + addDateTestCase(TIME_NOW); + addDateTestCase(TIME_NOW - TZ_ADJUST); + + // 2005 + addDateTestCase(UTC_01_JAN_2005); + addDateTestCase(UTC_01_JAN_2005 - 1000); + addDateTestCase(UTC_01_JAN_2005 - TZ_ADJUST); + + test(); + + function addTestCase() { + new TestCase( + status, + expect, + actual); + } + + function addDateTestCase(date_given_in_milliseconds) { + var s = 'new Date(' + date_given_in_milliseconds + ')'; + givenDate = new Date(date_given_in_milliseconds); + + status = 'd = ' + s + + '; d == new Date(d.toDateString() + " " + d.toLocaleTimeString())'; + expect = givenDate.toString(); + actual = new Date(givenDate.toDateString() + + ' ' + givenDate.toLocaleTimeString()).toString(); + addTestCase(); + } +}); diff --git a/js/src/tests/non262/Date/UTC-convert-all-arguments.js b/js/src/tests/non262/Date/UTC-convert-all-arguments.js new file mode 100644 index 0000000000..2fee8b951d --- /dev/null +++ b/js/src/tests/non262/Date/UTC-convert-all-arguments.js @@ -0,0 +1,70 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommonn.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 1160356; +var summary = + "Date.UTC must convert *all* arguments to number, not return NaN early if " + + "a non-finite argument is encountered"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function expectThrowTypeError(f, i) +{ + try + { + f(); + throw new Error("didn't throw"); + } + catch (e) + { + assertEq(e, 42, "index " + i + ": expected 42, got " + e); + } +} + +var bad = + { toString: function() { throw 17; }, valueOf: function() { throw 42; } }; + +var args = + [ + [bad], + + [NaN, bad], + [Infinity, bad], + [1970, bad], + + [1970, NaN, bad], + [1970, Infinity, bad], + [1970, 4, bad], + + [1970, 4, NaN, bad], + [1970, 4, Infinity, bad], + [1970, 4, 17, bad], + + [1970, 4, 17, NaN, bad], + [1970, 4, 17, Infinity, bad], + [1970, 4, 17, 13, bad], + + [1970, 4, 17, 13, NaN, bad], + [1970, 4, 17, 13, Infinity, bad], + [1970, 4, 17, 13, 37, bad], + + [1970, 4, 17, 13, 37, NaN, bad], + [1970, 4, 17, 13, 37, Infinity, bad], + [1970, 4, 17, 13, 37, 23, bad], + ]; + +for (var i = 0, len = args.length; i < len; i++) + expectThrowTypeError(function() { Date.UTC.apply(null, args[i]); }, i); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Date/browser.js b/js/src/tests/non262/Date/browser.js new file mode 100644 index 0000000000..e2c7f6d317 --- /dev/null +++ b/js/src/tests/non262/Date/browser.js @@ -0,0 +1,12 @@ +if (typeof getDefaultLocale === "undefined") { + var getDefaultLocale = SpecialPowers.Cu.getJSTestingFunctions().getDefaultLocale; +} +if (typeof setDefaultLocale === "undefined") { + var setDefaultLocale = SpecialPowers.Cu.getJSTestingFunctions().setDefaultLocale; +} +if (typeof getTimeZone === "undefined") { + var getTimeZone = SpecialPowers.Cu.getJSTestingFunctions().getTimeZone; +} +if (typeof setTimeZone === "undefined") { + var setTimeZone = SpecialPowers.Cu.getJSTestingFunctions().setTimeZone; +} diff --git a/js/src/tests/non262/Date/constructor-convert-all-arguments.js b/js/src/tests/non262/Date/constructor-convert-all-arguments.js new file mode 100644 index 0000000000..3a281cae22 --- /dev/null +++ b/js/src/tests/non262/Date/constructor-convert-all-arguments.js @@ -0,0 +1,70 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommonn.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 1160356; +var summary = + "new Date(...) must convert *all* arguments to number, not return NaN " + + "early if a non-finite argument is encountered"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function expectThrowTypeError(f, i) +{ + try + { + f(); + throw new Error("didn't throw"); + } + catch (e) + { + assertEq(e, 42, "index " + i + ": expected 42, got " + e); + } +} + +var bad = + { toString: function() { throw 17; }, valueOf: function() { throw 42; } }; + +var funcs = + [ + function() { new Date(bad); }, + + function() { new Date(NaN, bad); }, + function() { new Date(Infinity, bad); }, + function() { new Date(1970, bad); }, + + function() { new Date(1970, NaN, bad); }, + function() { new Date(1970, Infinity, bad); }, + function() { new Date(1970, 4, bad); }, + + function() { new Date(1970, 4, NaN, bad); }, + function() { new Date(1970, 4, Infinity, bad); }, + function() { new Date(1970, 4, 17, bad); }, + + function() { new Date(1970, 4, 17, NaN, bad); }, + function() { new Date(1970, 4, 17, Infinity, bad); }, + function() { new Date(1970, 4, 17, 13, bad); }, + + function() { new Date(1970, 4, 17, 13, NaN, bad); }, + function() { new Date(1970, 4, 17, 13, Infinity, bad); }, + function() { new Date(1970, 4, 17, 13, 37, bad); }, + + function() { new Date(1970, 4, 17, 13, 37, NaN, bad); }, + function() { new Date(1970, 4, 17, 13, 37, Infinity, bad); }, + function() { new Date(1970, 4, 17, 13, 37, 23, bad); }, + ]; + +for (var i = 0, len = funcs.length; i < len; i++) + expectThrowTypeError(funcs[i]); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Date/constructor-one-Date-argument.js b/js/src/tests/non262/Date/constructor-one-Date-argument.js new file mode 100644 index 0000000000..718c413731 --- /dev/null +++ b/js/src/tests/non262/Date/constructor-one-Date-argument.js @@ -0,0 +1,40 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommonn.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 1187233; +var summary = + "Passing a Date object to |new Date()| should copy it, not convert it to " + + "a primitive and create it from that."; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +Date.prototype.toString = Date.prototype.valueOf = null; +var d = new Date(new Date(8675309)); +assertEq(d.getTime(), 8675309); + +Date.prototype.valueOf = () => 42; +d = new Date(new Date(8675309)); +assertEq(d.getTime(), 8675309); + +var D = newGlobal().Date; + +D.prototype.toString = D.prototype.valueOf = null; +var d = new Date(new D(3141592654)); +assertEq(d.getTime(), 3141592654); + +D.prototype.valueOf = () => 525600; +d = new Date(new D(3141592654)); +assertEq(d.getTime(), 3141592654); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Date/constructor-one-argument.js b/js/src/tests/non262/Date/constructor-one-argument.js new file mode 100644 index 0000000000..d7acd33aad --- /dev/null +++ b/js/src/tests/non262/Date/constructor-one-argument.js @@ -0,0 +1,26 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommonn.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 738511; +var summary = + "new Date(value) should call ToPrimitive on value before testing for " + + "string-ness"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +assertEq(new Date(new String("2012-01-31T00:00:00.000Z")).valueOf(), + 1327968000000, + "Date constructor passed a String object should parse it"); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Date/dashed-date.js b/js/src/tests/non262/Date/dashed-date.js new file mode 100644 index 0000000000..e479904098 --- /dev/null +++ b/js/src/tests/non262/Date/dashed-date.js @@ -0,0 +1,155 @@ +const tests = [ + // ==== Date only ==== + + // dd-MMM-yyyy + ["24-Apr-2023", "2023-04-24T00:00:00"], + ["24-apr-2023", "2023-04-24T00:00:00"], + ["24-April-2023", "2023-04-24T00:00:00"], + ["24-APRIL-2023", "2023-04-24T00:00:00"], + ["24-Apr-2033", "2033-04-24T00:00:00"], + + ["24-Apr-0023", "0023-04-24T00:00:00"], + + // dd-MMM-yy + ["24-Apr-23", "2023-04-24T00:00:00"], + ["24-Apr-33", "2033-04-24T00:00:00"], + + // dd-MMM-yyy + ["24-Apr-023", "2023-04-24T00:00:00"], + + // MMM-dd-yyyy + ["Apr-24-2023", "2023-04-24T00:00:00"], + ["apr-24-2023", "2023-04-24T00:00:00"], + ["April-24-2023", "2023-04-24T00:00:00"], + ["APRIL-24-2023", "2023-04-24T00:00:00"], + ["Apr-24-2033", "2033-04-24T00:00:00"], + + ["Apr-24-0023", "0023-04-24T00:00:00"], + + // MMM-dd-yy + ["Apr-24-23", "2023-04-24T00:00:00"], + ["Apr-24-33", "2033-04-24T00:00:00"], + + // MMM-dd-yyy + ["Apr-24-023", "2023-04-24T00:00:00"], + + // yyyy-MM-dd + ["2023-Apr-24", "2023-04-24T00:00:00"], + ["2033-Apr-24", "2033-04-24T00:00:00"], + + // yy-MM-dd + ["33-Apr-24", "2033-04-24T00:00:00"], + + // yyy-MM-dd + ["033-Apr-24", "2033-04-24T00:00:00"], + + // ==== Date followed by hour and TZ ==== + + ["24-Apr-2023 12:34:56", "2023-04-24T12:34:56"], + ["24-Apr-2023 Mon 12:34:56", "2023-04-24T12:34:56"], + ["24-Apr-2023 (Mon) 12:34:56", "2023-04-24T12:34:56"], + ["24-Apr-2023(Mon)12:34:56", "2023-04-24T12:34:56"], + + ["24-Apr-2023,12:34:56", "2023-04-24T12:34:56"], + ["24-Apr-2023,Mon 12:34:56", "2023-04-24T12:34:56"], + + ["24-Apr-2023 12:34:56 GMT", "2023-04-24T12:34:56Z"], + ["24-Apr-2023 12:34:56 +04", "2023-04-24T12:34:56+04:00"], + ["24-Apr-2023 12:34:56 +04:30", "2023-04-24T12:34:56+04:30"], + ["24-Apr-2023 12:34:56 -04", "2023-04-24T12:34:56-04:00"], + ["24-Apr-2023 12:34:56 -04:30", "2023-04-24T12:34:56-04:30"], + + ["24-Apr-2023 GMT", "2023-04-24T00:00:00Z"], + ["24-Apr-2023GMT", "2023-04-24T00:00:00Z"], + ["24-Apr-2023GMT-04", "2023-04-24T00:00:00-04:00"], + ["24-Apr-2023GMT-04:30", "2023-04-24T00:00:00-04:30"], + ["24-Apr-2023GMT+04", "2023-04-24T00:00:00+04:00"], + ["24-Apr-2023GMT+04:30", "2023-04-24T00:00:00+04:30"], + + ["24-Apr-2023,GMT", "2023-04-24T00:00:00Z"], + ["24-Apr-2023/GMT", "2023-04-24T00:00:00Z"], + + ["24-Apr-2023/12:34:56", "2023-04-24T12:34:56"], + + ["Apr-24-2023 12:34:56", "2023-04-24T12:34:56"], + ["Apr-24-2023 12:34:56 GMT", "2023-04-24T12:34:56Z"], + ["Apr-24-2023 12:34:56 +04", "2023-04-24T12:34:56+04:00"], + ["Apr-24-2023 12:34:56 +04:30", "2023-04-24T12:34:56+04:30"], + + // ==== non dd-MMM-yyyy. Uses fallback path ==== + + // Extra delimiter. + ["24-Apr- 2023", "2023-04-24T00:00:00"], + ["24-Apr -2023", "-002023-04-24T00:00:00"], + ["24- Apr-2023", "-002023-04-24T00:00:00"], + ["24 -Apr-2023", "-002023-04-24T00:00:00"], + + ["24-Apr-/2023", "2023-04-24T00:00:00"], + ["24-Apr/-2023", "-002023-04-24T00:00:00"], + ["24-/Apr-2023", "-002023-04-24T00:00:00"], + ["24/-Apr-2023", "-002023-04-24T00:00:00"], + + ["24-Apr-()2023", "2023-04-24T00:00:00"], + ["24-Apr()-2023", "-002023-04-24T00:00:00"], + ["24-()Apr-2023", "-002023-04-24T00:00:00"], + ["24()-Apr-2023", "-002023-04-24T00:00:00"], + + // mday being 3+ digits + ["024-Apr-2023", "-002023-04-24T00:00:00"], + ["0024-Apr-2023", "-002023-04-24T00:00:00"], + + // year w/ 5 or 6 digits + ["24-Apr-10000", "+010000-04-24T00:00:00"], + ["24-Apr-10000 10:00", "+010000-04-24T10:00:00"], + ["24-Apr-275760", "+275760-04-24T00:00:00"], + + // Delimiter other than space after prefix + ["24-Apr-2312.10:13:14", "2312-04-24T10:13:14"], + ["24-Apr-2312,10:13:14", "2312-04-24T10:13:14"], + ["24-Apr-2312-10:13:14", "2312-04-24T10:13:14"], + ["24-Apr-2312-04:30", "2312-04-24T04:30:00"], + ["24-Apr-2312/10:13:14", "2312-04-24T10:13:14"], + ["24-Apr-2312()10:13:14", "2312-04-24T10:13:14"], + // Open paren only comments out the time + ["24-Apr-2312(10:13:14", "2312-04-24T00:00:00"], + + // mday being 3+ digits, while year being 2-3 digits. + ["024-Apr-23", "2023-04-24T00:00:00"], + ["024-Apr-023", "2023-04-24T00:00:00"], +]; + +for (const [testString, isoString] of tests) { + const testDate = new Date(testString); + const isoDate = new Date(isoString); + + assertEq(testDate.getTime(), isoDate.getTime(), + testString); +} + +const invalidTests = [ + // mday being out of range. + "32-01-32", + + // Duplicate date. + "2012-Apr-08 12/12/12", + + // > TimeClip limit + "13-Sep-275760 00:00:01 GMT", + + // Rejected delimiters after prefix + "24-Apr-2312T10:13:14", + "24-Apr-2312:10:13:14", + "24-Apr-2312^10:13:14", + "24-Apr-2312|10:13:14", + "24-Apr-2312~10:13:14", + "24-Apr-2312+10:13:14", + "24-Apr-2312=10:13:14", + "24-Apr-2312?10:13:14", +]; + +for (const testString of invalidTests) { + assertEq(Number.isNaN(new Date(testString).getTime()), true, testString); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/defaultvalue.js b/js/src/tests/non262/Date/defaultvalue.js new file mode 100644 index 0000000000..2fc5887d18 --- /dev/null +++ b/js/src/tests/non262/Date/defaultvalue.js @@ -0,0 +1,190 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommonn.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 645464; +var summary = + "[[DefaultValue]] behavior wrong for Date with overridden valueOf/toString"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function allTests() +{ + var DS = new Date(2010, 1, 1).toString(); + + // equality + + var d = new Date(2010, 1, 1); + assertEq(d == DS, true); + + var d2 = new Date(2010, 1, 1); + d2.valueOf = function() { assertEq(arguments.length, 0); return 17; }; + assertEq(d2 == DS, true); + + var d3 = new Date(2010, 1, 1); + d3.toString = function() { return 42; }; + assertEq(d3 == 42, true); + + function testEquality() + { + var d = new Date(2010, 1, 1); + assertEq(d == DS, true); + + var d2 = new Date(2010, 1, 1); + d2.valueOf = function() { assertEq(arguments.length, 0); return 17; }; + assertEq(d2 == DS, true); + + var d3 = new Date(2010, 1, 1); + d3.toString = function() { return 42; }; + assertEq(d3 == 42, true); + } + testEquality(); + + + // addition of Date to number + + var d = new Date(2010, 1, 1); + assertEq(d + 5, DS + "5"); + + var d2 = new Date(2010, 1, 1); + d2.toString = function() { return 9; }; + assertEq(d2 + 3, 9 + 3); + + var d3 = new Date(2010, 1, 1); + d3.valueOf = function() { assertEq(arguments.length, 0); return 17; }; + assertEq(d3 + 5, DS + "5"); + + function testDateNumberAddition() + { + var d = new Date(2010, 1, 1); + assertEq(d + 5, DS + "5"); + + var d2 = new Date(2010, 1, 1); + d2.toString = function() { return 9; }; + assertEq(d2 + 3, 9 + 3); + + var d3 = new Date(2010, 1, 1); + d3.valueOf = function() { assertEq(arguments.length, 0); return 17; }; + assertEq(d3 + 5, DS + "5"); + } + testDateNumberAddition(); + + + // addition of Date to Date + + var d = new Date(2010, 1, 1); + assertEq(d + d, DS + DS); + + var d2 = new Date(2010, 1, 1); + d2.toString = function() { return 5; }; + assertEq(d2 + d2, 10); + + var d3 = new Date(2010, 1, 1); + d3.valueOf = function() { assertEq(arguments.length, 0); return 8.5; }; + assertEq(d3 + d3, DS + DS); + + function testDateDateAddition() + { + var d = new Date(2010, 1, 1); + assertEq(d + d, DS + DS); + + var d2 = new Date(2010, 1, 1); + d2.toString = function() { return 5; }; + assertEq(d2 + d2, 10); + + var d3 = new Date(2010, 1, 1); + d3.valueOf = function() { assertEq(arguments.length, 0); return 8.5; }; + assertEq(d3 + d3, DS + DS); + } + testDateDateAddition(); + + + // Date as bracketed property name + + var obj = { 8: 42, 9: 73 }; + obj[DS] = 17; + + var d = new Date(2010, 1, 1); + assertEq(obj[d], 17); + + var d2 = new Date(2010, 1, 1); + d2.valueOf = function() { assertEq(arguments.length, 0); return 8; } + assertEq(obj[d2], 17); + + var d3 = new Date(2010, 1, 1); + d3.toString = function() { return 9; }; + assertEq(obj[d3], 73); + + function testPropertyName() + { + var obj = { 8: 42, 9: 73 }; + obj[DS] = 17; + + var d = new Date(2010, 1, 1); + assertEq(obj[d], 17); + + var d2 = new Date(2010, 1, 1); + d2.valueOf = function() { assertEq(arguments.length, 0); return 8; } + assertEq(obj[d2], 17); + + var d3 = new Date(2010, 1, 1); + d3.toString = function() { return 9; }; + assertEq(obj[d3], 73); + } + testPropertyName(); + + + // Date as property name with |in| operator + + var obj = {}; + obj[DS] = 5; + + var d = new Date(2010, 1, 1); + assertEq(d in obj, true); + + var d2 = new Date(2010, 1, 1); + d2.toString = function() { return "baz"; }; + assertEq(d2 in { baz: 42 }, true); + + var d3 = new Date(2010, 1, 1); + d3.valueOf = function() { assertEq(arguments.length, 0); return "quux"; }; + assertEq(d3 in obj, true); + + function testInOperatorName() + { + var obj = {}; + obj[DS] = 5; + + var d = new Date(2010, 1, 1); + assertEq(d in obj, true); + + var d2 = new Date(2010, 1, 1); + d2.toString = function() { return "baz"; }; + assertEq(d2 in { baz: 42 }, true); + + var d3 = new Date(2010, 1, 1); + d3.valueOf = function() { assertEq(arguments.length, 0); return "quux"; }; + assertEq(d3 in obj, true); + } + testInOperatorName(); +} + +allTests(); + +if (typeof newGlobal === "function") +{ + Date = newGlobal().Date; + allTests(); +} + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Date/dst-offset-caching-1-of-8.js b/js/src/tests/non262/Date/dst-offset-caching-1-of-8.js new file mode 100644 index 0000000000..95a88e9a92 --- /dev/null +++ b/js/src/tests/non262/Date/dst-offset-caching-1-of-8.js @@ -0,0 +1,6 @@ +// |reftest| slow +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +runDSTOffsetCachingTestsFraction(1, 8); diff --git a/js/src/tests/non262/Date/dst-offset-caching-2-of-8.js b/js/src/tests/non262/Date/dst-offset-caching-2-of-8.js new file mode 100644 index 0000000000..0810f91176 --- /dev/null +++ b/js/src/tests/non262/Date/dst-offset-caching-2-of-8.js @@ -0,0 +1,6 @@ +// |reftest| slow +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +runDSTOffsetCachingTestsFraction(2, 8); diff --git a/js/src/tests/non262/Date/dst-offset-caching-3-of-8.js b/js/src/tests/non262/Date/dst-offset-caching-3-of-8.js new file mode 100644 index 0000000000..a70559afa3 --- /dev/null +++ b/js/src/tests/non262/Date/dst-offset-caching-3-of-8.js @@ -0,0 +1,6 @@ +// |reftest| slow +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +runDSTOffsetCachingTestsFraction(3, 8); diff --git a/js/src/tests/non262/Date/dst-offset-caching-4-of-8.js b/js/src/tests/non262/Date/dst-offset-caching-4-of-8.js new file mode 100644 index 0000000000..3bda28d617 --- /dev/null +++ b/js/src/tests/non262/Date/dst-offset-caching-4-of-8.js @@ -0,0 +1,6 @@ +// |reftest| slow +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +runDSTOffsetCachingTestsFraction(4, 8); diff --git a/js/src/tests/non262/Date/dst-offset-caching-5-of-8.js b/js/src/tests/non262/Date/dst-offset-caching-5-of-8.js new file mode 100644 index 0000000000..a15692ff0d --- /dev/null +++ b/js/src/tests/non262/Date/dst-offset-caching-5-of-8.js @@ -0,0 +1,6 @@ +// |reftest| slow +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +runDSTOffsetCachingTestsFraction(5, 8); diff --git a/js/src/tests/non262/Date/dst-offset-caching-6-of-8.js b/js/src/tests/non262/Date/dst-offset-caching-6-of-8.js new file mode 100644 index 0000000000..d2ce8e90c8 --- /dev/null +++ b/js/src/tests/non262/Date/dst-offset-caching-6-of-8.js @@ -0,0 +1,6 @@ +// |reftest| slow +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +runDSTOffsetCachingTestsFraction(6, 8); diff --git a/js/src/tests/non262/Date/dst-offset-caching-7-of-8.js b/js/src/tests/non262/Date/dst-offset-caching-7-of-8.js new file mode 100644 index 0000000000..aaa560c202 --- /dev/null +++ b/js/src/tests/non262/Date/dst-offset-caching-7-of-8.js @@ -0,0 +1,6 @@ +// |reftest| slow +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +runDSTOffsetCachingTestsFraction(7, 8); diff --git a/js/src/tests/non262/Date/dst-offset-caching-8-of-8.js b/js/src/tests/non262/Date/dst-offset-caching-8-of-8.js new file mode 100644 index 0000000000..30a6f781b8 --- /dev/null +++ b/js/src/tests/non262/Date/dst-offset-caching-8-of-8.js @@ -0,0 +1,6 @@ +// |reftest| slow +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +runDSTOffsetCachingTestsFraction(8, 8); diff --git a/js/src/tests/non262/Date/equality-to-boolean.js b/js/src/tests/non262/Date/equality-to-boolean.js new file mode 100644 index 0000000000..c60319b9d9 --- /dev/null +++ b/js/src/tests/non262/Date/equality-to-boolean.js @@ -0,0 +1,39 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +print("Test for correct implementation of |Date == boolean| and vice versa"); + +/************** + * BEGIN TEST * + **************/ + +Date.prototype.toString = function() { return 1; }; +Date.prototype.valueOf = function() { return 0; }; + +/* + * ES5 11.9.3 doesn't directly handle obj == boolean. Instead it translates it + * as follows: + * + * obj == boolean + * ↳ obj == ToNumber(boolean), per step 7 + * ↳ ToPrimitive(obj) == ToNumber(boolean), per step 9 + * + * ToPrimitive calls [[DefaultValue]] with no hint. For Date objects this is + * treated as if it were instead called with hint String. That calls toString, + * which returns 1, so Date objects here should compare equal to true and + * unequal to false. + */ +assertEq(new Date == true, true); +assertEq(new Date == false, false); + +/* == is symmetric. */ +assertEq(true == new Date, true); +assertEq(false == new Date, false); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Date/fractions.js b/js/src/tests/non262/Date/fractions.js new file mode 100644 index 0000000000..30dd663ddd --- /dev/null +++ b/js/src/tests/non262/Date/fractions.js @@ -0,0 +1,24 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommonn.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 771946; +var summary = "Fractional days, months, years shouldn't trigger asserts"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +new Date(0).setFullYear(1.5); +new Date(0).setUTCDate(1.5); +new Date(0).setMonth(1.5); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Date/non-iso.js b/js/src/tests/non262/Date/non-iso.js new file mode 100644 index 0000000000..28d7c51952 --- /dev/null +++ b/js/src/tests/non262/Date/non-iso.js @@ -0,0 +1,71 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommonn.org/licenses/publicdomain/ + */ + +/* + * For the sake of cross compatibility with other implementations we + * follow the W3C "NOTE-datetime" specification when parsing dates of + * the form YYYY-MM-DDTHH:MM:SS save for a few exceptions: months, days, hours + * minutes, and seconds may be either one _or_ two digits long, and the 'T' + * preceding the time part may be replaced with a space. So, a string like + * "1997-3-8 1:1:1" will parse successfully. See bug: 1203298 + */ + +/************** + * BEGIN TEST * + **************/ + +assertEq(new Date("1997-03-08 1:1:1.01").getTime(), + new Date("1997-03-08T01:01:01.01").getTime()); +assertEq(new Date("1997-03-08 11:19:20").getTime(), + new Date("1997-03-08T11:19:20").getTime()); +assertEq(new Date("1997-3-08 11:19:20").getTime(), + new Date("1997-03-08T11:19:20").getTime()); +assertEq(new Date("1997-3-8 11:19:20").getTime(), + new Date("1997-03-08T11:19:20").getTime()); +assertEq(new Date("+001997-3-8 11:19:20").getTime(), + new Date("1997-03-08T11:19:20").getTime()); +assertEq(new Date("+001997-03-8 11:19:20").getTime(), + new Date("1997-03-08T11:19:20").getTime()); +assertEq(new Date("1997-03-08 11:19").getTime(), + new Date("1997-03-08T11:19").getTime()); +assertEq(new Date("1997-03-08 1:19").getTime(), + new Date("1997-03-08T01:19").getTime()); +assertEq(new Date("1997-03-08 1:1").getTime(), + new Date("1997-03-08T01:01").getTime()); +assertEq(new Date("1997-03-08 1:1:01").getTime(), + new Date("1997-03-08T01:01:01").getTime()); +assertEq(new Date("1997-03-08 1:1:1").getTime(), + new Date("1997-03-08T01:01:01").getTime()); +assertEq(new Date("1997-03-08 11").getTime(), + new Date("1997-03-08T11").getTime()); // Date(NaN) +assertEq(new Date("1997-03-08 11:19:10-07").getTime(), + new Date("1997-03-08 11:19:10-0700").getTime()); +assertEq(new Date("1997-03-08T11:19:10-07").getTime(), + new Date(NaN).getTime()); +assertEq(new Date("1997-03-08T").getTime(), + new Date(NaN).getTime()); +assertEq(new Date("1997-3-8T11:19:20").getTime(), + new Date(NaN).getTime()); +assertEq(new Date("1997-03-8T11:19:20").getTime(), + new Date(NaN).getTime()); +assertEq(new Date("+001997-3-8T11:19:20").getTime(), + new Date(NaN).getTime()); +assertEq(new Date("+001997-3-08T11:19:20").getTime(), + new Date(NaN).getTime()); +assertEq(new Date("1997-03-08T1:19").getTime(), + new Date(NaN).getTime()); +assertEq(new Date("1997-03-08T1:1").getTime(), + new Date(NaN).getTime()); +assertEq(new Date("1997-03-08T1:1:01").getTime(), + new Date(NaN).getTime()); +assertEq(new Date("1997-03-08T1:1:1").getTime(), + new Date(NaN).getTime()); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Date/parse-dashed-numeric-date.js b/js/src/tests/non262/Date/parse-dashed-numeric-date.js new file mode 100644 index 0000000000..b0bd1a35ec --- /dev/null +++ b/js/src/tests/non262/Date/parse-dashed-numeric-date.js @@ -0,0 +1,133 @@ +// |reftest| skip-if(xulRuntime.OS=="WINNT") -- Windows doesn't accept IANA names for the TZ env variable +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +inTimeZone("MST", () => { + // The upper limit is from the TimeClip algorithm: + // https://tc39.es/ecma262/#sec-timeclip + // https://tc39.es/ecma262/#sec-utc-t + // + // The result is in localtime but the limit is processed in GMT, which + // is why these are offset from the actual limit of 275760-09-13T00:00:00 + // (in this case by 7h, because we're testing in MST) + const accepted = { + "19999-09-12": new Date(19999, Month.September, 12), + "19999-9-1": new Date(19999, Month.September, 1), + "19999-9-1 ": new Date(19999, Month.September, 1), + "275760-09-12": new Date(275760, Month.September, 12), + "275760-09-12 17:00:00": new Date(275760, Month.September, 12, 17), + "19999-09-12 (comment) 23:00:00": new Date(19999, Month.September, 12, 23), + "19999-09-12 22:00:00 GMT-0800": new Date(19999, Month.September, 12, 23), + + // Single digit mon or mday + "2021-09-1": new Date(2021, Month.September, 1), + "2021-9-01": new Date(2021, Month.September, 1), + "2021-9-1": new Date(2021, Month.September, 1), + + // 1-12 for first number should be month + "1-09-12": new Date(2012, Month.January, 9), + "1-09-2012": new Date(2012, Month.January, 9), + "12-09-12": new Date(2012, Month.December, 9), + + // 32-99 for first number is the year... + // 32-49 are 2032-2049, 50-99 are 1950-1999 + "32-09-12": new Date(2032, Month.September, 12), + "49-09-12": new Date(2049, Month.September, 12), + "50-09-12": new Date(1950, Month.September, 12), + "99-09-12": new Date(1999, Month.September, 12), + + // Year 0 is 2000 + "0-9-12": new Date(2000, Month.September, 12), + "9-12-0": new Date(2000, Month.September, 12), + + // 3-digit year is also fine + "999-09-12": new Date(999, Month.September, 12), + + // Bug 1617258 (result is -7 hours) + "2020-03-24 12:54:40 AM +00:00": new Date(2020, Month.March, 23, 17, 54, 40), + + // Oddball time formats for Chrome parity + "9999-09-12 :00:01": new Date(9999, Month.September, 12, 0, 1), + // TODO: This one still does not have parity- bug 1858595 + "9999-09-12 01::01": new Date(9999, Month.September, 12, 1, 1, 0), + + // mday > # of days in mon rolls over to the next month + // as long as mday <= 31 (2022 is not a leap year) + // These are processed as ISO dates, therefore are in GMT + "2022-02-29": new Date(2022, Month.February, 28, 17), + "2022-02-30": new Date(2022, Month.March, 1, 17), + "2022-02-31": new Date(2022, Month.March, 2, 17), + + // No space before time zone + "19999-9-1MST": new Date(19999, Month.September, 1), + "19999-9-1GMT-07": new Date(19999, Month.September, 1), + + // Delimiter other than space after prefix + "19999-9-1.10:13:14": new Date(19999, Month.September, 1, 10, 13, 14), + "19999-9-1,10:13:14": new Date(19999, Month.September, 1, 10, 13, 14), + "19999-9-1-10:13:14": new Date(19999, Month.September, 1, 10, 13, 14), + "19999-9-1-4:30": new Date(19999, Month.September, 1, 4, 30), + "19999-9-1/10:13:14": new Date(19999, Month.September, 1, 10, 13, 14), + "19999-9-1()10:13:14": new Date(19999, Month.September, 1, 10, 13, 14), + // Open paren only comments out the time + "19999-9-1(10:13:14": new Date(19999, Month.September, 1), + }; + const rejected = [ + "275760-09-12 17:00:01", + "275760-09-13", + + // Rejected delimiters after prefix + "19999-09-12T00:00:00", + "19999-09-12:00:00:00", + "19999-09-12^00:00:00", + "19999-09-12|00:00:00", + "19999-09-12~00:00:00", + "19999-09-12+00:00:00", + "19999-09-12=00:00:00", + "19999-09-12?00:00:00", + + // 13-31 for first number is invalid (after 31 can be parsed as YY-MM-DD), + // but 32 is still no good if the last number is a YYYY + "13-09-12", + "13-09-2012", + "31-09-12", + "31-09-2012", + "32-09-2012", + + // mday > 31 is invalid, does not roll over to the next month + "2022-02-32", + // month > 12 + "2022-13-30", + + // 00 for mon or mday + "0000-00-00", + "0000-01-00", + "0000-00-01", + ]; + + for (const [test, dateObject] of Object.entries(accepted)) { + const testDate = new Date(test); + + assertEq( + false, isNaN(testDate), + `${test} should be accepted.` + ); + + assertEq( + testDate.getTime(), dateObject.getTime(), + `"${test}" should be ${dateObject} (got ${testDate}).` + ); + } + + for (const reject of rejected) { + assertEq( + true, isNaN(new Date(reject)), + `"${reject}" should be rejected.` + ); + } +}); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/parse-day-of-week.js b/js/src/tests/non262/Date/parse-day-of-week.js new file mode 100644 index 0000000000..08bcd3ee05 --- /dev/null +++ b/js/src/tests/non262/Date/parse-day-of-week.js @@ -0,0 +1,93 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const expectedDate = new Date("1995-09-26T00:00:00"); + +// Each prefix will be tested with each format: +const prefixes = [ + "Tuesday, ", + "Tuesday ", + "Tuesday,", + "Tuesday.", + "Tuesday-", + "Tuesday/", + + // Case insensitive + "tuesday, ", + "tUeSdAy ", + + // Abbreviations are valid down to the first character + "Tuesda ", + "Tue ", + "T ", + "t,", + + // Floating delimiters at beginning are allowed/ignored + " ", + ",", + ", ", + ".", + "-", + "/", + + // It doesn't actually need to be the correct day of the week, or + // a day of week at all...you can put anything there + "Monday ", + "foo bar " +]; +const formats = [ + "Sep 26 1995", + "26 Sep 1995", + "September 26, 1995", + "26-Sep-1995", + "1995-9-26", + // ISO format is non-formal with day of week in front + "1995-09-26", + + // You can put anything between the month and mday + "Sep foo bar 26 1995", + "Sep-foo bar-26 1995", + "Sep-foo-bar-26 1995", + + // Redundant month names are allowed + "Sep sep 26 1995", + "Sep 26 sep 1995", + // Edge case: if multiple month names, use the last one + "Jan 26 1995 sep", +]; + +const rejected = [ + "Sep 26 foo 1995", + "Sep 26 1995 foo", + "1995 foo Sep 26", + "foo2 Sep 26 1995", +]; + +for (const format of formats) { + for (const prefix of prefixes) { + const test = prefix + format; + const testDate = new Date(test); + + assertEq( + false, isNaN(testDate), + `${test} should be accepted.` + ); + + assertEq( + testDate.getTime(), expectedDate.getTime(), + `"${test}" should be ${expectedDate} (got ${testDate}).` + ); + } +} + +for (const reject of rejected) { + assertEq( + true, isNaN(new Date(reject)), + `"${reject}" should be rejected.` + ); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/parse-from-tostring-methods.js b/js/src/tests/non262/Date/parse-from-tostring-methods.js new file mode 100644 index 0000000000..b6bf577bb0 --- /dev/null +++ b/js/src/tests/non262/Date/parse-from-tostring-methods.js @@ -0,0 +1,31 @@ +let dates = [ + "0041-09-23", "+000041-09-23", "-000041-09-23", + "0091-09-23", "+000091-09-23", "-000091-09-23", + "0217-09-23", "+000217-09-23", "-000217-09-23", + "2017-09-23", "+002017-09-23", "-002017-09-23", + "+022017-09-23", "-022017-09-23", + "+202017-09-23", "-202017-09-23", +]; + +for (let date of dates) { + let d = new Date(date); + let timeValue = d.valueOf(); + + assertEq(Number.isNaN(timeValue), false, `Cannot parse "${date}" as ISO date-only form`); + + // Ensure parsing the results of toString(), toUTCString(), and toISOString() + // gives the same time value as required by 20.3.3.2 Date.parse. + // + // Additional requirement not present in ES2019 draft rev 7acacc524213058a2368b5fa751fac7ea08ba230: + // The time zone offset must not contain seconds (or milliseconds) for |Date.parse(x.toString())| + // to be equal to |x.valueOf()|. + let tz = d.getTimezoneOffset(); + if (Math.trunc(tz) === tz) { + assertEq(Date.parse(d.toString()), timeValue, `Cannot parse from toString() of "${date}"`); + } + assertEq(Date.parse(d.toUTCString()), timeValue, `Cannot parse from toUTCString() of "${date}"`); + assertEq(Date.parse(d.toISOString()), timeValue, `Cannot parse from toISOString() of "${date}"`); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/parse-keywords.js b/js/src/tests/non262/Date/parse-keywords.js new file mode 100644 index 0000000000..c834bbfe0b --- /dev/null +++ b/js/src/tests/non262/Date/parse-keywords.js @@ -0,0 +1,50 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const accepted = { + "Sep 26 1995 UT": "1995-09-26T00:00:00Z", + "Sep 26 1995 UTC": "1995-09-26T00:00:00Z", + "Sep 26 1995 GMT": "1995-09-26T00:00:00Z", + "Sep 26 1995 EST": "1995-09-26T00:00:00-0500", + "Sep 26 1995 est": "1995-09-26T00:00:00-0500", + "Sep 26 1995 10:00 am": "1995-09-26T10:00:00", + "Sep 26 1995 10:00 AM": "1995-09-26T10:00:00", + "Sep 26 1995 10:00 pm": "1995-09-26T22:00:00", + "Sep 26 Thurs 1995 Mon 10:thursday:00": "1995-09-26T10:00:00", +}; +const rejected = [ + "Sep 26 1995 G", + "Sep 26 1995 GM", + "Sep 26 1995 E", + "Sep 26 1995 ES", + "Sep 26 1995 10:00 a", + "Sep 26 1995 10:00 p", + "0/zx", +]; + +for (const [test, expected] of Object.entries(accepted)) { + const testDate = new Date(test); + const expectedDate = new Date(expected); + + assertEq( + false, isNaN(testDate), + `${test} should be accepted.` + ); + + assertEq( + testDate.getTime(), expectedDate.getTime(), + `"${test}" should be ${expectedDate} (got ${testDate}).` + ); +} + +for (const reject of rejected) { + assertEq( + true, isNaN(new Date(reject)), + `"${reject}" should be rejected.` + ); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/parse-milliseconds.js b/js/src/tests/non262/Date/parse-milliseconds.js new file mode 100644 index 0000000000..ddaa73e4e4 --- /dev/null +++ b/js/src/tests/non262/Date/parse-milliseconds.js @@ -0,0 +1,66 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const accepted = { + "Sep 26 1995 12:34:56.789": "1995-09-26T12:34:56.789", + "Sep 26 1995 12:34:56.7": "1995-09-26T12:34:56.700", + "Sep 26 1995 12:34:56.78": "1995-09-26T12:34:56.780", + "Sep 26 1995 12:34:56.001": "1995-09-26T12:34:56.001", + + "Sep 26 1995 12:34:56.789Z": "1995-09-26T12:34:56.789Z", + "Sep 26 1995 12:34:56.789 -0500": "1995-09-26T12:34:56.789-0500", + "Sep 26 1995 12:34:56.789-0500": "1995-09-26T12:34:56.789-0500", + + // Note that the trailing '.' without milliseconds is rejected. + // Rejecting this case could be done trivially, but Chrome allows it, + // so we will allow it for parity. + "Sep 26 1995 12:34:56.789.": "1995-09-26T12:34:56.789", + + // Truncate after 3 digits + "Sep 26 1995 12:34:56.0001": "1995-09-26T12:34:56", + "Sep 26 1995 12:34:56.0009": "1995-09-26T12:34:56", + "Sep 26 1995 12:34:56.999": "1995-09-26T12:34:56.999", + "Sep 26 1995 12:34:56.9990": "1995-09-26T12:34:56.999", + "Sep 26 1995 12:34:56.9999": "1995-09-26T12:34:56.999", + // Before bug 746529, it would have rounded up here: + "Sep 26 1995 12:34:56.99999999999999996": "1995-09-26T12:34:56.999", + "Sep 26 1995 12:34:56.50099999999999996": "1995-09-26T12:34:56.500", + "Sep 26 1995 12:34:56.00099999999999996": "1995-09-26T12:34:56", + "Sep 26 1995 12:34:56.000999999999999999999": "1995-09-26T12:34:56", +}; +const rejected = [ + "Sep 26 1995 12:34:56.", + "Sep 26 1995 12:34:56:789", + "Sep 26 1995 12:34:56..789", +]; + +// Sanity check to make sure these are being parsed to the right precision +// Otherwise, the comparisons in the above object could still pass +assertEq(Date.parse("1970-01-01T00:00:00.99999999999999996Z"), 999); + +for (const [test, expected] of Object.entries(accepted)) { + const testDate = new Date(test); + const expectedDate = new Date(expected); + + assertEq( + false, isNaN(testDate), + `${test} should be accepted.` + ); + + assertEq( + testDate.getTime(), expectedDate.getTime(), + `"${test}" should be ${expectedDate} (got ${testDate}).` + ); +} + +for (const reject of rejected) { + assertEq( + true, isNaN(new Date(reject)), + `"${reject}" should be rejected.` + ); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/parse-month.js b/js/src/tests/non262/Date/parse-month.js new file mode 100644 index 0000000000..09bfdec50d --- /dev/null +++ b/js/src/tests/non262/Date/parse-month.js @@ -0,0 +1,91 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const accepted = { + // Make sure all 12 months work + "Jan 01 2000": "2000-01-01T00:00:00", + "Feb 01 2000": "2000-02-01T00:00:00", + "Mar 01 2000": "2000-03-01T00:00:00", + "Apr 01 2000": "2000-04-01T00:00:00", + "May 01 2000": "2000-05-01T00:00:00", + "Jun 01 2000": "2000-06-01T00:00:00", + "Jul 01 2000": "2000-07-01T00:00:00", + "Aug 01 2000": "2000-08-01T00:00:00", + "Sep 01 2000": "2000-09-01T00:00:00", + "Oct 01 2000": "2000-10-01T00:00:00", + "Nov 01 2000": "2000-11-01T00:00:00", + "Dec 01 2000": "2000-12-01T00:00:00", + + // Anything after the 3rd character should be ignored + "Janfoo 01 2000": "2000-01-01T00:00:00", + "Febfoo 01 2000": "2000-02-01T00:00:00", + "Marfoo 01 2000": "2000-03-01T00:00:00", + "Aprfoo 01 2000": "2000-04-01T00:00:00", + "Mayfoo 01 2000": "2000-05-01T00:00:00", + "Junfoo 01 2000": "2000-06-01T00:00:00", + "Julfoo 01 2000": "2000-07-01T00:00:00", + "Augfoo 01 2000": "2000-08-01T00:00:00", + "Sepfoo 01 2000": "2000-09-01T00:00:00", + "Octfoo 01 2000": "2000-10-01T00:00:00", + "Novfoo 01 2000": "2000-11-01T00:00:00", + "Decfoo 01 2000": "2000-12-01T00:00:00", + + // Check different formats + "Janfoo-01-2000": "2000-01-01T00:00:00", + "01-Janfoo-2000": "2000-01-01T00:00:00", + "01 Janfoo 2000": "2000-01-01T00:00:00", +}; +const rejected = [ + "Foo 01 2000", + + "Ja 01 2000", + "Fe 01 2000", + "Ma 01 2000", + "Ap 01 2000", + "Ma 01 2000", + "Ju 01 2000", + "Au 01 2000", + "Se 01 2000", + "Oc 01 2000", + "No 01 2000", + "De 01 2000", + + "Jax 01 2000", + "Fex 01 2000", + "Max 01 2000", + "Apx 01 2000", + "Max 01 2000", + "Jux 01 2000", + "Aux 01 2000", + "Sex 01 2000", + "Ocx 01 2000", + "Nox 01 2000", + "Dex 01 2000", +]; + +for (const [test, expected] of Object.entries(accepted)) { + const testDate = new Date(test); + const expectedDate = new Date(expected); + + assertEq( + false, isNaN(testDate), + `${test} should be accepted.` + ); + + assertEq( + testDate.getTime(), expectedDate.getTime(), + `"${test}" should be ${expectedDate} (got ${testDate}).` + ); +} + +for (const reject of rejected) { + assertEq( + true, isNaN(new Date(reject)), + `"${reject}" should be rejected.` + ); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/parse-num-preceding-alpha.js b/js/src/tests/non262/Date/parse-num-preceding-alpha.js new file mode 100644 index 0000000000..ebcdfc98f4 --- /dev/null +++ b/js/src/tests/non262/Date/parse-num-preceding-alpha.js @@ -0,0 +1,44 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +assertEq(new Date("15AUG2015").getTime(), + new Date(2015, Month.August, 15).getTime()); + +assertEq(new Date("Aug 15, 2015 10:00am").getTime(), + new Date(2015, Month.August, 15, 10).getTime()); +assertEq(new Date("Aug 15, 2015 10:00pm").getTime(), + new Date(2015, Month.August, 15, 22).getTime()); + +const rejects = [ + "2023+/08/12", + "2023/08+/12", + "12Aug2023Sat", + "2023/08/12 12:34:56+0900+", + "2023/08/12 12:34:56+0900-", + "2023/08/12 12:34:56+09:00+", + "2023/08/12 12:34:56+09:00-", + "2023/08/12 12:34:56 +09:00+", + "2023/08/12 12:34:56GMT+0900,", + "2023/08/12 12:34:56GMT+0900.", + "2023/08/12 12:34:56GMT+0900/", + "2023/08/12 12:34:56GMT+0900+", + "2023/08/12 12:34:56GMT+0900-", + "2023/08/12 12:34:56GMT+09:30,", + "2023/08/12 12:34:56GMT+09:30.", + "2023/08/12 12:34:56GMT+09:30/", + "2023/08/12 12:34:56GMT+09:30+", + "2023/08/12 12:34:56GMT+09:30-", + "2023/08/12 12:34:56 +09:30+", + "2023/08/12 12:34:56 GMT+09:30+", + "2023/08/12 12:34:56.", + "2023/08/12 12:34:56.-0900", + "2023/08/12 12:34:56PST", +]; +for (const reject of rejects) { + assertEq(isNaN(new Date(reject)), true, `"${reject}" should be rejected.`); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/parse-period.js b/js/src/tests/non262/Date/parse-period.js new file mode 100644 index 0000000000..835512823e --- /dev/null +++ b/js/src/tests/non262/Date/parse-period.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(xulRuntime.OS=="WINNT") -- Windows doesn't accept IANA names for the TZ env variable +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const tests = [ + "Aug. 15, 2015", + "Aug.. 15, 2015", + "Aug.15.2015", + "15.Aug.2015", + "Aug 15 2015 12:00 am.", + "Sat. Aug 15 2015", + "2015.08.15", + "2015.08.15.00:00:00", + + // These look weird but are accepted for Chrome parity + // (dots are valid delimiters and are essentially ignored) + "2015./08/15 00:00:00", + "2015/08./15 00:00:00", +]; +const rejected = [ + "2015/08/15 00:00:00.", + "2015/08/15 00:00:00.GMT", +]; + +for (const test of tests) { + assertEq(new Date(test).getTime(), + new Date(2015, Month.August, 15).getTime(), + `"${test}" should be accepted.`); +} + +for (const reject of rejected) { + assertEq( + true, isNaN(new Date(reject)), + `"${reject}" should be rejected.` + ); +} + +inTimeZone("Etc/GMT-1", () => { + let dt = new Date("Aug 15 2015 GMT."); + assertEq(dt.getTime(), new Date(2015, Month.August, 15, 1).getTime()); +}); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/parse-single-number.js b/js/src/tests/non262/Date/parse-single-number.js new file mode 100644 index 0000000000..e28d6183cd --- /dev/null +++ b/js/src/tests/non262/Date/parse-single-number.js @@ -0,0 +1,60 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const accepted = { + "0": "2000-01-01T00:00:00", + "1": "2001-01-01T00:00:00", + "12": "2001-12-01T00:00:00", + "32": "2032-01-01T00:00:00", + "49": "2049-01-01T00:00:00", + "50": "1950-01-01T00:00:00", + "99": "1999-01-01T00:00:00", + "100": "0100-01-01T00:00:00", + "999": "0999-01-01T00:00:00", + "1000": "1000-01-01T00:00:00Z", + "1000-": "1000-01-01T00:00:00", + "20009": "+020009-01-01T00:00:00", + "+20009": "+020009-01-01T00:00:00", + + // Rejecting e.g. S22 (see rejected patterns below) shouldn't + // reject mday directly after month name + "Sep26 1995": "1995-09-26T00:00:00", +}; +const rejected = [ + "S22", + "5C", + "Sep26 foo 1995", +]; + +for (const [test, expected] of Object.entries(accepted)) { + const testDate = new Date(test); + const expectedDate = new Date(expected); + + assertEq( + false, isNaN(testDate), + `${test} should be accepted.` + ); + + assertEq( + testDate.getTime(), expectedDate.getTime(), + `"${test}" should be ${expectedDate} (got ${testDate}).` + ); +} + +for (let i = 13; i <= 31; ++i) { + assertEq( + true, isNaN(new Date(`${i}`)), + `"${i}" should be rejected.` + ); +} +for (const reject of rejected) { + assertEq( + true, isNaN(new Date(reject)), + `"${reject}" should be rejected.` + ); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/parse-time-zone.js b/js/src/tests/non262/Date/parse-time-zone.js new file mode 100644 index 0000000000..c239822b04 --- /dev/null +++ b/js/src/tests/non262/Date/parse-time-zone.js @@ -0,0 +1,10 @@ +// |reftest| skip-if(xulRuntime.OS=="WINNT") -- Windows doesn't accept IANA names for the TZ env variable + +// bug 1676708 +inTimeZone("Europe/London", () => { + let dt = new Date("Wed Nov 11 2020 19:18:50 GMT+0010"); + assertEq(dt.getTime(), new Date(2020, Month.November, 11, 19, 08, 50).getTime()); +}); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/parse-timezone-without-gmt.js b/js/src/tests/non262/Date/parse-timezone-without-gmt.js new file mode 100644 index 0000000000..c8e2d8e4bb --- /dev/null +++ b/js/src/tests/non262/Date/parse-timezone-without-gmt.js @@ -0,0 +1,118 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const accepted = { + "1995-09-26T00:00:00-0500": [ + "Sep 26 1995 GMT-0500", + "Sep 26 1995 00:00:00 GMT-0500", + "Sep 26 1995 00:00:00 gmt-0500", + "Sep 26 1995 00:00:00 Z-0500", + "Sep 26 1995 00:00:00 UT-0500", + "Sep 26 1995 00:00:00 UTC-0500", + "Sep 26 1995 00:00:00 -0500", + "Sep 26 1995 00:00:00 -05", + "Sep 26 1995 00:00:00-0500", + "Sep 26 1995 00:00:00-05", + "Sep 26 1995 00:00 -0500", + "Sep 26 1995 00:00 -05", + "Sep 26 1995 00:00-0500", + "Sep 26 1995 00:00-05", + ], + + "1995-09-26T00:00:00+0500": [ + "Sep 26 1995 GMT+0500", + "Sep 26 1995 00:00:00 GMT+0500", + "Sep 26 1995 00:00:00 gmt+0500", + "Sep 26 1995 00:00:00 Z+0500", + "Sep 26 1995 00:00:00 UT+0500", + "Sep 26 1995 00:00:00 UTC+0500", + "Sep 26 1995 00:00:00 +0500", + "Sep 26 1995 00:00:00 +05", + "Sep 26 1995 00:00:00+0500", + "Sep 26 1995 00:00:00+05", + "Sep 26 1995 00:00 +0500", + "Sep 26 1995 00:00 +05", + "Sep 26 1995 00:00+0500", + "Sep 26 1995 00:00+05", + ], + + "1995-09-26T00:00:00-0430": [ + "Sep 26 1995 GMT-04:30", + "Sep 26 1995 00:00:00 GMT-04:30", + "Sep 26 1995 00:00:00 -04:30", + "Sep 26 1995 00:00:00-04:30", + "Sep 26 1995 00:00 -04:30", + "Sep 26 1995 00:00-04:30", + ], + + "1995-09-26T00:00:00+0430": [ + "Sep 26 1995 GMT+04:30", + "Sep 26 1995 00:00:00 GMT+04:30", + "Sep 26 1995 00:00:00 +04:30", + "Sep 26 1995 00:00:00+04:30", + "Sep 26 1995 00:00 +04:30", + "Sep 26 1995 00:00+04:30", + ], + + "1995-09-26T04:30:00": [ + "Sep 26 1995-04:30", + "1995-09-26-04:30", + "1995-Sep-26-04:30", + ], +}; +const rejected = [ + "Sep 26 1995 -05", + "Sep 26 1995-05", + "Sep 26 1995 -04:30", + "1995-09-26 -05", + "1995-09-26 -04:30", + "1995-09-26-05", + "1995-Sep-26 -05", + "1995-Sep-26-05", + "1995-Sep-26,-05", + + "Sep 26 1995 +05", + "Sep 26 1995 +04:30", + "Sep 26 1995+05", + "Sep 26 1995+04:30", + "1995-09-26 +05", + "1995-09-26+05", + "1995-Sep-26 +05", + "1995-Sep-26+05", + "1995-Sep-26,+05", + + // These cases are allowed by V8 but are parsed as GMT-XXXX no matter the + // abbreviation (e.g. EST-0500 is parsed as GMT-0500 and not GMT-1000). This + // is unexpected and so we are explicitly rejecting them. + "Sep 26 1995 00:00:00 EST-0500", + "Sep 26 1995 00:00:00 MDT-0500", +]; + +for (const [expected, patterns] of Object.entries(accepted)) { + for (const test of patterns) { + const testDate = new Date(test); + const expectedDate = new Date(expected); + + assertEq( + false, isNaN(testDate), + `${test} should be accepted.` + ); + + assertEq( + testDate.getTime(), expectedDate.getTime(), + `"${test}" should be ${expectedDate} (got ${testDate}).` + ); + } +} + +for (const reject of rejected) { + assertEq( + true, isNaN(new Date(reject)), + `"${reject}" should be rejected.` + ); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/parse-year-after-timezone.js b/js/src/tests/non262/Date/parse-year-after-timezone.js new file mode 100644 index 0000000000..333d408718 --- /dev/null +++ b/js/src/tests/non262/Date/parse-year-after-timezone.js @@ -0,0 +1,42 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const accepted = { + "1997-11-05T00:00:00-0800": [ + "Wed Nov 05 00:00:00 GMT-0800 1997", + "Nov 05 00:00:00 GMT-0800 1997", + "Nov-05 00:00:00 GMT-0800 1997", + "05-Nov 00:00:00 GMT-0800 1997", + "05-Nov GMT-0800 1997", + ], + + "-001997-11-05T00:00:00-0800": [ + "Wed Nov 05 00:00:00 GMT-0800 -1997", + "Nov 05 00:00:00 GMT-0800 -1997", + "Nov-05 00:00:00 GMT-0800 -1997", + "05-Nov 00:00:00 GMT-0800 -1997", + "05-Nov GMT-0800 -1997", + ], +}; + +for (const [expected, patterns] of Object.entries(accepted)) { + for (const test of patterns) { + const testDate = new Date(test); + const expectedDate = new Date(expected); + + assertEq( + false, isNaN(testDate), + `${test} should be accepted.` + ); + + assertEq( + testDate.getTime(), expectedDate.getTime(), + `"${test}" should be ${expectedDate} (got ${testDate}).` + ); + } +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/parse-zulu-time.js b/js/src/tests/non262/Date/parse-zulu-time.js new file mode 100644 index 0000000000..a7bcd3bd00 --- /dev/null +++ b/js/src/tests/non262/Date/parse-zulu-time.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(xulRuntime.OS=="WINNT") -- Windows doesn't accept IANA names for the TZ env variable +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const tests = [ + "Aug 15, 2015 10:00Z", + "08/15/2015 10:00Z", + "Aug 15, 2015 10:00 Z", +] + +inTimeZone("GMT", () => { + for (const test of tests) { + const dt = new Date(test); + assertEq(dt.getTime(), new Date(2015, Month.August, 15, 10).getTime()); + } +}); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/prototype-is-not-a-date.js b/js/src/tests/non262/Date/prototype-is-not-a-date.js new file mode 100644 index 0000000000..26f0c3e859 --- /dev/null +++ b/js/src/tests/non262/Date/prototype-is-not-a-date.js @@ -0,0 +1,15 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 861219; +var summary = "Date.prototype isn't an instance of Date"; + +print(BUGNUMBER + ": " + summary); + +assertEq(Date.prototype instanceof Date, false); +assertEq(Date.prototype.__proto__, Object.prototype); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/regress-188211.js b/js/src/tests/non262/Date/regress-188211.js new file mode 100644 index 0000000000..663611b81b --- /dev/null +++ b/js/src/tests/non262/Date/regress-188211.js @@ -0,0 +1,27 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 188211; +var summary = 'Date.prototype.toLocaleString() error on future dates'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +var dt; + +dt = new Date(208e10); +printStatus(dt+''); +expect = true; +actual = dt.toLocaleString().indexOf('2035') >= 0; +reportCompare(expect, actual, summary + ': new Date(208e10)'); + +dt = new Date(209e10); +printStatus(dt+''); +expect = true; +actual = dt.toLocaleString().indexOf('2036') >= 0; +reportCompare(expect, actual, summary + ': new Date(209e10)'); diff --git a/js/src/tests/non262/Date/regress-301738-01.js b/js/src/tests/non262/Date/regress-301738-01.js new file mode 100644 index 0000000000..8f5ae7d304 --- /dev/null +++ b/js/src/tests/non262/Date/regress-301738-01.js @@ -0,0 +1,97 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 301738; +var summary = 'Date parse compatibilty with MSIE'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +/* + Case 1. The input string contains an English month name. + The form of the string can be month f l, or f month l, or + f l month which each evaluate to the same date. + If f and l are both greater than or equal to 70, or + both less than 70, the date is invalid. + The year is taken to be the greater of the values f, l. + If the year is greater than or equal to 70 and less than 100, + it is considered to be the number of years after 1900. +*/ + +var month = 'January'; +var f; +var l; + +f = l = 0; +expect = true; + +actual = isNaN(new Date(month + ' ' + f + ' ' + l)); +reportCompare(expect, actual, 'January 0 0 is invalid'); + +actual = isNaN(new Date(f + ' ' + l + ' ' + month)); +reportCompare(expect, actual, '0 0 January is invalid'); + +actual = isNaN(new Date(f + ' ' + month + ' ' + l)); +reportCompare(expect, actual, '0 January 0 is invalid'); + +f = l = 70; + +actual = isNaN(new Date(month + ' ' + f + ' ' + l)); +reportCompare(expect, actual, 'January 70 70 is invalid'); + +actual = isNaN(new Date(f + ' ' + l + ' ' + month)); +reportCompare(expect, actual, '70 70 January is invalid'); + +actual = isNaN(new Date(f + ' ' + month + ' ' + l)); +reportCompare(expect, actual, '70 January 70 is invalid'); + +f = 100; +l = 15; + +// year, month, day +expect = new Date(f, 0, l).toString(); + +actual = new Date(month + ' ' + f + ' ' + l).toString(); +reportCompare(expect, actual, 'month f l'); + +actual = new Date(f + ' ' + l + ' ' + month).toString(); +reportCompare(expect, actual, 'f l month'); + +actual = new Date(f + ' ' + month + ' ' + l).toString(); +reportCompare(expect, actual, 'f month l'); + +f = 80; +l = 15; + +// year, month, day +expect = (new Date(f, 0, l)).toString(); + +actual = (new Date(month + ' ' + f + ' ' + l)).toString(); +reportCompare(expect, actual, 'month f l'); + +actual = (new Date(f + ' ' + l + ' ' + month)).toString(); +reportCompare(expect, actual, 'f l month'); + +actual = (new Date(f + ' ' + month + ' ' + l)).toString(); +reportCompare(expect, actual, 'f month l'); + +f = 2040; +l = 15; + +// year, month, day +expect = (new Date(f, 0, l)).toString(); + +actual = (new Date(month + ' ' + f + ' ' + l)).toString(); +reportCompare(expect, actual, 'month f l'); + +actual = (new Date(f + ' ' + l + ' ' + month)).toString(); +reportCompare(expect, actual, 'f l month'); + +actual = (new Date(f + ' ' + month + ' ' + l)).toString(); +reportCompare(expect, actual, 'f month l'); + diff --git a/js/src/tests/non262/Date/regress-309925-01.js b/js/src/tests/non262/Date/regress-309925-01.js new file mode 100644 index 0000000000..ee6daaffc4 --- /dev/null +++ b/js/src/tests/non262/Date/regress-309925-01.js @@ -0,0 +1,15 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 309925; +var summary = 'Correctly parse Date strings with HH:MM'; +var actual = new Date('Sep 24, 11:58 105') + ''; +var expect = new Date('Sep 24, 11:58:00 105') + ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/Date/regress-309925-02.js b/js/src/tests/non262/Date/regress-309925-02.js new file mode 100644 index 0000000000..60bbfc33b0 --- /dev/null +++ b/js/src/tests/non262/Date/regress-309925-02.js @@ -0,0 +1,15 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 309925; +var summary = 'Correctly parse Date strings with HH:MM(comment)'; +var actual = new Date('Sep 24, 11:58(comment) 105') + ''; +var expect = new Date('Sep 24, 11:58:00 (comment) 105') + ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/Date/regress-346027.js b/js/src/tests/non262/Date/regress-346027.js new file mode 100644 index 0000000000..ad1dc9e55f --- /dev/null +++ b/js/src/tests/non262/Date/regress-346027.js @@ -0,0 +1,27 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 346027; +var summary = 'Date.prototype.setFullYear()'; +var actual = ''; +var expect = true; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + var d = new Date(); + d.setFullYear(); + actual = isNaN(d.getFullYear()); + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/Date/regress-346363.js b/js/src/tests/non262/Date/regress-346363.js new file mode 100644 index 0000000000..6381899fbc --- /dev/null +++ b/js/src/tests/non262/Date/regress-346363.js @@ -0,0 +1,28 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 346363; +var summary = 'Date.prototype.setFullYear()'; +var actual = ''; +var expect = true; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + var d = new Date(); + d.setFullYear(); + d.setFullYear(2006); + actual = d.getFullYear() == 2006; + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/Date/regress-452786.js b/js/src/tests/non262/Date/regress-452786.js new file mode 100644 index 0000000000..c8943b1f99 --- /dev/null +++ b/js/src/tests/non262/Date/regress-452786.js @@ -0,0 +1,30 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 452786; +var summary = 'Do not crash with (new Date()).getMonth.call(new Function())'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + try + { + (new Date()).getMonth.call(new Function()); + } + catch(ex) + { + } + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/Date/reset-time-zone-cache-same-offset.js b/js/src/tests/non262/Date/reset-time-zone-cache-same-offset.js new file mode 100644 index 0000000000..56c9fc262c --- /dev/null +++ b/js/src/tests/non262/Date/reset-time-zone-cache-same-offset.js @@ -0,0 +1,30 @@ +// |reftest| skip-if(xulRuntime.OS=="WINNT") -- Windows doesn't accept IANA names for the TZ env variable + +const testCases = [ + { + timeZone: "Europe/London", + string: "Tue Aug 14 2018 00:00:00 GMT+0100 (BST)", + alternativeTimeZones: ["British Summer Time"], + localeString: "8/14/2018, 12:00:00 AM GMT+1", + }, + { + timeZone: "UTC", + string: "Tue Aug 14 2018 00:00:00 GMT+0000 (UTC)", + alternativeTimeZones: ["Coordinated Universal Time"], + localeString: "8/14/2018, 12:00:00 AM UTC", + }, +]; + +// Repeat twice to test both transitions (Europe/London -> UTC and UTC -> Europe/London). +for (let i = 0; i < 2; ++i) { + for (let {timeZone, string, localeString, alternativeTimeZones} of testCases) { + setTimeZone(timeZone); + + let dt = new Date(2018, 8 - 1, 14); + assertDateTime(dt, string, ...alternativeTimeZones); + assertEq(dt.toLocaleString("en-US", {timeZoneName: "short"}), localeString); + } +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/setTime-argument-shortcircuiting.js b/js/src/tests/non262/Date/setTime-argument-shortcircuiting.js new file mode 100644 index 0000000000..7e67d03742 --- /dev/null +++ b/js/src/tests/non262/Date/setTime-argument-shortcircuiting.js @@ -0,0 +1,147 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +print("Test for correct short-circuiting implementation of Date.set methods"); + +/************** + * BEGIN TEST * + **************/ +var global = 0; +var date; + +/* Test that methods don't short circuit argument evaluation. */ +date = new Date(0).setSeconds(NaN, {valueOf:function(){global = 3}}); +assertEq(global, 3); + +date = new Date(0).setUTCSeconds(NaN, {valueOf:function(){global = 4}}); +assertEq(global, 4); + +date = new Date(0).setMinutes(NaN, {valueOf:function(){global = 5}}); +assertEq(global, 5); + +date = new Date(0).setUTCMinutes(NaN, {valueOf:function(){global = 6}}); +assertEq(global, 6); + +date = new Date(0).setHours(NaN, {valueOf:function(){global = 7}}); +assertEq(global, 7); + +date = new Date(0).setUTCHours(NaN, {valueOf:function(){global = 8}}); +assertEq(global, 8); + +date = new Date(0).setMonth(NaN, {valueOf:function(){global = 11}}); +assertEq(global, 11); + +date = new Date(0).setUTCMonth(NaN, {valueOf:function(){global = 12}}); +assertEq(global, 12); + +date = new Date(0).setFullYear(NaN, {valueOf:function(){global = 13}}); +assertEq(global, 13); + +date = new Date(0).setUTCFullYear(NaN, {valueOf:function(){global = 14}}); +assertEq(global, 14); + + + +/* Test that argument evaluation is not short circuited if Date == NaN */ +date = new Date(NaN).setMilliseconds({valueOf:function(){global = 15}}); +assertEq(global, 15); + +date = new Date(NaN).setUTCMilliseconds({valueOf:function(){global = 16}}); +assertEq(global, 16); + +date = new Date(NaN).setSeconds({valueOf:function(){global = 17}}); +assertEq(global, 17); + +date = new Date(NaN).setUTCSeconds({valueOf:function(){global = 18}}); +assertEq(global, 18); + +date = new Date(NaN).setMinutes({valueOf:function(){global = 19}}); +assertEq(global, 19); + +date = new Date(NaN).setUTCMinutes({valueOf:function(){global = 20}}); +assertEq(global, 20); + +date = new Date(NaN).setHours({valueOf:function(){global = 21}}); +assertEq(global, 21); + +date = new Date(NaN).setUTCHours({valueOf:function(){global = 22}}); +assertEq(global, 22); + +date = new Date(NaN).setDate({valueOf:function(){global = 23}}); +assertEq(global, 23); + +date = new Date(NaN).setUTCDate({valueOf:function(){global = 24}}); +assertEq(global, 24); + +date = new Date(NaN).setMonth({valueOf:function(){global = 25}}); +assertEq(global, 25); + +date = new Date(NaN).setUTCMonth({valueOf:function(){global = 26}}); +assertEq(global, 26); + +date = new Date(NaN).setFullYear({valueOf:function(){global = 27}}); +assertEq(global, 27); + +date = new Date(NaN).setUTCFullYear({valueOf:function(){global = 28}}); +assertEq(global, 28); + + +/* Test the combination of the above two. */ +date = new Date(NaN).setSeconds(NaN, {valueOf:function(){global = 31}}); +assertEq(global, 31); + +date = new Date(NaN).setUTCSeconds(NaN, {valueOf:function(){global = 32}}); +assertEq(global, 32); + +date = new Date(NaN).setMinutes(NaN, {valueOf:function(){global = 33}}); +assertEq(global, 33); + +date = new Date(NaN).setUTCMinutes(NaN, {valueOf:function(){global = 34}}); +assertEq(global, 34); + +date = new Date(NaN).setHours(NaN, {valueOf:function(){global = 35}}); +assertEq(global, 35); + +date = new Date(NaN).setUTCHours(NaN, {valueOf:function(){global = 36}}); +assertEq(global, 36); + +date = new Date(NaN).setMonth(NaN, {valueOf:function(){global = 39}}); +assertEq(global, 39); + +date = new Date(NaN).setUTCMonth(NaN, {valueOf:function(){global = 40}}); +assertEq(global, 40); + +date = new Date(NaN).setFullYear(NaN, {valueOf:function(){global = 41}}); +assertEq(global, 41); + +date = new Date(NaN).setUTCFullYear(NaN, {valueOf:function(){global = 42}}); +assertEq(global, 42); + + +/*Test two methods evaluation*/ +var secondGlobal = 0; + +date = new Date(NaN).setFullYear({valueOf:function(){global = 43}}, {valueOf:function(){secondGlobal = 1}}); +assertEq(global, 43); +assertEq(secondGlobal, 1); + +date = new Date(0).setFullYear(NaN, {valueOf:function(){global = 44}}, {valueOf:function(){secondGlobal = 2}}); +assertEq(global, 44); +assertEq(secondGlobal, 2); + + +/* Test year methods*/ +date = new Date(0).setYear({valueOf:function(){global = 45}}); +assertEq(global, 45); + +date = new Date(NaN).setYear({valueOf:function(){global = 46}}); +assertEq(global, 46); + + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Date/shell.js b/js/src/tests/non262/Date/shell.js new file mode 100644 index 0000000000..9246c1eaaa --- /dev/null +++ b/js/src/tests/non262/Date/shell.js @@ -0,0 +1,311 @@ +/** + * Date functions used by tests in Date suite + */ +(function(global) { + const msPerDay = 1000 * 60 * 60 * 24; + const msPerHour = 1000 * 60 * 60; + global.msPerHour = msPerHour; + + // Offset of tester's time zone from UTC. + const TZ_DIFF = GetRawTimezoneOffset(); + global.TZ_ADJUST = TZ_DIFF * msPerHour; + + const UTC_01_JAN_1900 = -2208988800000; + const UTC_01_JAN_2000 = 946684800000; + const UTC_29_FEB_2000 = UTC_01_JAN_2000 + 31 * msPerDay + 28 * msPerDay; + const UTC_01_JAN_2005 = UTC_01_JAN_2000 + TimeInYear(2000) + TimeInYear(2001) + + TimeInYear(2002) + TimeInYear(2003) + TimeInYear(2004); + global.UTC_01_JAN_1900 = UTC_01_JAN_1900; + global.UTC_01_JAN_2000 = UTC_01_JAN_2000; + global.UTC_29_FEB_2000 = UTC_29_FEB_2000; + global.UTC_01_JAN_2005 = UTC_01_JAN_2005; + + /* + * Originally, the test suite used a hard-coded value TZ_DIFF = -8. + * But that was only valid for testers in the Pacific Standard Time Zone! + * We calculate the proper number dynamically for any tester. We just + * have to be careful not to use a date subject to Daylight Savings Time... + */ + function GetRawTimezoneOffset() { + let t1 = new Date(2000, 1, 1).getTimezoneOffset(); + let t2 = new Date(2000, 1 + 6, 1).getTimezoneOffset(); + + // 1) Time zone without daylight saving time. + // 2) Northern hemisphere with daylight saving time. + if ((t1 - t2) >= 0) + return -t1 / 60; + + // 3) Southern hemisphere with daylight saving time. + return -t2 / 60; + } + + function DaysInYear(y) { + return y % 4 === 0 && (y % 100 !== 0 || y % 400 === 0) ? 366 : 365; + } + + function TimeInYear(y) { + return DaysInYear(y) * msPerDay; + } + + function getDefaultTimeZone() { + var tz = getTimeZone(); + switch (tz) { + case "EST": + case "EDT": + return "EST5EDT"; + + case "CST": + case "CDT": + return "CST6CDT"; + + case "MST": + case "MDT": + return "MST7MDT"; + + case "PST": + case "PDT": + return "PST8PDT"; + + default: + // Other time zones abbrevations are not supported. + return tz; + } + } + + function getDefaultLocale() { + // If the default locale looks like a BCP-47 language tag, return it. + var locale = global.getDefaultLocale(); + if (locale.match(/^[a-z][a-z0-9\-]+$/i)) + return locale; + + // Otherwise use undefined to reset to the default locale. + return undefined; + } + + let defaultTimeZone = null; + let defaultLocale = null; + + // Run the given test in the requested time zone. + function inTimeZone(tzname, fn) { + if (defaultTimeZone === null) + defaultTimeZone = getDefaultTimeZone(); + + setTimeZone(tzname); + try { + fn(); + } finally { + setTimeZone(defaultTimeZone); + } + } + global.inTimeZone = inTimeZone; + + // Run the given test with the requested locale. + function withLocale(locale, fn) { + if (defaultLocale === null) + defaultLocale = getDefaultLocale(); + + setDefaultLocale(locale); + try { + fn(); + } finally { + setDefaultLocale(defaultLocale); + } + } + global.withLocale = withLocale; + + const Month = { + January: 0, + February: 1, + March: 2, + April: 3, + May: 4, + June: 5, + July: 6, + August: 7, + September: 8, + October: 9, + November: 10, + December: 11, + }; + global.Month = Month; + + const weekdays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"].join("|"); + const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"].join("|"); + const datePart = String.raw `(?:${weekdays}) (?:${months}) \d{2}`; + const timePart = String.raw `\d{4,6} \d{2}:\d{2}:\d{2} GMT[+-]\d{4}`; + const dateTimeRE = new RegExp(String.raw `^(${datePart} ${timePart})(?: \((.+)\))?$`); + + function assertDateTime(date, expected, ...alternativeTimeZones) { + let actual = date.toString(); + assertEq(dateTimeRE.test(expected), true, `${expected}`); + assertEq(dateTimeRE.test(actual), true, `${actual}`); + + let [, expectedDateTime, expectedTimeZone] = dateTimeRE.exec(expected); + let [, actualDateTime, actualTimeZone] = dateTimeRE.exec(actual); + + assertEq(actualDateTime, expectedDateTime); + + // The time zone identifier is optional, so only compare its value if + // it's present in |actual| and |expected|. + if (expectedTimeZone !== undefined && actualTimeZone !== undefined) { + // Test against the alternative time zone identifiers if necessary. + if (actualTimeZone !== expectedTimeZone) { + for (let alternativeTimeZone of alternativeTimeZones) { + if (actualTimeZone === alternativeTimeZone) { + expectedTimeZone = alternativeTimeZone; + break; + } + } + } + assertEq(actualTimeZone, expectedTimeZone); + } + } + global.assertDateTime = assertDateTime; +})(this); + + +function runDSTOffsetCachingTestsFraction(part, parts) +{ + var BUGNUMBER = 563938; + var summary = 'Cache DST offsets to improve SunSpider score'; + + print(BUGNUMBER + ": " + summary); + + var MAX_UNIX_TIMET = 2145859200; // "2037-12-31T08:00:00.000Z" (PST8PDT based!) + var RANGE_EXPANSION_AMOUNT = 30 * 24 * 60 * 60; + + /** + * Computes the time zone offset in minutes at the given timestamp. + */ + function tzOffsetFromUnixTimestamp(timestamp) + { + var d = new Date(NaN); + d.setTime(timestamp); // local slot = NaN, UTC slot = timestamp + return d.getTimezoneOffset(); // get UTC, calculate local => diff in minutes + } + + /** + * Clear the DST offset cache, leaving it initialized to include a timestamp + * completely unlike the provided one (i.e. one very, very far away in time + * from it). Thus an immediately following lookup for the provided timestamp + * will cache-miss and compute a clean value. + */ + function clearDSTOffsetCache(undesiredTimestamp) + { + var opposite = (undesiredTimestamp + MAX_UNIX_TIMET / 2) % MAX_UNIX_TIMET; + + // Generic purge to known, but not necessarily desired, state + tzOffsetFromUnixTimestamp(0); + tzOffsetFromUnixTimestamp(MAX_UNIX_TIMET); + + // Purge to desired state. Cycle 2x in case opposite or undesiredTimestamp + // is close to 0 or MAX_UNIX_TIMET. + tzOffsetFromUnixTimestamp(opposite); + tzOffsetFromUnixTimestamp(undesiredTimestamp); + tzOffsetFromUnixTimestamp(opposite); + tzOffsetFromUnixTimestamp(undesiredTimestamp); + } + + function computeCanonicalTZOffset(timestamp) + { + clearDSTOffsetCache(timestamp); + return tzOffsetFromUnixTimestamp(timestamp); + } + + var TEST_TIMESTAMPS_SECONDS = + [ + // Special-ish timestamps + 0, + RANGE_EXPANSION_AMOUNT, + MAX_UNIX_TIMET, + ]; + + var ONE_DAY = 24 * 60 * 60; + var EIGHTY_THREE_HOURS = 83 * 60 * 60; + var NINETY_EIGHT_HOURS = 98 * 60 * 60; + function nextIncrement(i) + { + return i === EIGHTY_THREE_HOURS ? NINETY_EIGHT_HOURS : EIGHTY_THREE_HOURS; + } + + // Now add a long sequence of non-special timestamps, from a fixed range, that + // overlaps a DST change by "a bit" on each side. 67 days should be enough + // displacement that we can occasionally exercise the implementation's + // thirty-day expansion and the DST-offset-change logic. Use two different + // increments just to be safe and catch something a single increment might not. + var DST_CHANGE_DATE = 1268553600; // March 14, 2010 + for (var t = DST_CHANGE_DATE - 67 * ONE_DAY, + i = nextIncrement(NINETY_EIGHT_HOURS), + end = DST_CHANGE_DATE + 67 * ONE_DAY; + t < end; + i = nextIncrement(i), t += i) + { + TEST_TIMESTAMPS_SECONDS.push(t); + } + + var TEST_TIMESTAMPS = + TEST_TIMESTAMPS_SECONDS.map(function(v) { return v * 1000; }); + + /************** + * BEGIN TEST * + **************/ + + // Compute the correct time zone offsets for all timestamps to be tested. + var CORRECT_TZOFFSETS = TEST_TIMESTAMPS.map(computeCanonicalTZOffset); + + // Intentionally and knowingly invoking every single logic path in the cache + // isn't easy for a human to get right (and know he's gotten it right), so + // let's do it the easy way: exhaustively try all possible four-date sequences + // selecting from our array of possible timestamps. + + var sz = TEST_TIMESTAMPS.length; + var start = Math.floor((part - 1) / parts * sz); + var end = Math.floor(part / parts * sz); + + print("Exhaustively testing timestamps " + + "[" + start + ", " + end + ") of " + sz + "..."); + + try + { + for (var i = start; i < end; i++) + { + print("Testing timestamp " + i + "..."); + + var t1 = TEST_TIMESTAMPS[i]; + for (var j = 0; j < sz; j++) + { + var t2 = TEST_TIMESTAMPS[j]; + for (var k = 0; k < sz; k++) + { + var t3 = TEST_TIMESTAMPS[k]; + for (var w = 0; w < sz; w++) + { + var t4 = TEST_TIMESTAMPS[w]; + + clearDSTOffsetCache(t1); + + var tzo1 = tzOffsetFromUnixTimestamp(t1); + var tzo2 = tzOffsetFromUnixTimestamp(t2); + var tzo3 = tzOffsetFromUnixTimestamp(t3); + var tzo4 = tzOffsetFromUnixTimestamp(t4); + + assertEq(tzo1, CORRECT_TZOFFSETS[i]); + assertEq(tzo2, CORRECT_TZOFFSETS[j]); + assertEq(tzo3, CORRECT_TZOFFSETS[k]); + assertEq(tzo4, CORRECT_TZOFFSETS[w]); + } + } + } + } + } + catch (e) + { + assertEq(true, false, + "Error when testing with timestamps " + + i + ", " + j + ", " + k + ", " + w + + " (" + t1 + ", " + t2 + ", " + t3 + ", " + t4 + ")!"); + } + + reportCompare(true, true); + print("All tests passed!"); +} diff --git a/js/src/tests/non262/Date/time-components-negative-zero.js b/js/src/tests/non262/Date/time-components-negative-zero.js new file mode 100644 index 0000000000..511dcc9fe4 --- /dev/null +++ b/js/src/tests/non262/Date/time-components-negative-zero.js @@ -0,0 +1,18 @@ +// Don't return negative zero for get[Hours,Minutes,Seconds,Milliseconds] for dates before 1970. + +let date = new Date(1955, 0, 1); +assertEq(date.getTime() < 0, true); +assertEq(date.getHours(), +0); +assertEq(date.getMinutes(), +0); +assertEq(date.getSeconds(), +0); +assertEq(date.getMilliseconds(), +0); + +let utc = new Date(Date.UTC(1955, 0, 1)); +assertEq(utc.getTime() < 0, true); +assertEq(utc.getUTCHours(), +0); +assertEq(utc.getUTCMinutes(), +0); +assertEq(utc.getUTCSeconds(), +0); +assertEq(utc.getUTCMilliseconds(), +0); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/time-zone-2038-pst.js b/js/src/tests/non262/Date/time-zone-2038-pst.js new file mode 100644 index 0000000000..2abad4dbfd --- /dev/null +++ b/js/src/tests/non262/Date/time-zone-2038-pst.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!xulRuntime.shell) + +assertEq(/^(PST|PDT)$/.test(getTimeZone()), true, + "The default time zone is set to PST8PDT for all jstests (when run in the shell)"); + +// U.S. daylight saving rules changed in 2007, excerpt from tzdata's +// northamerica file: +// NAME FROM TO IN ON AT SAVE LETTER/S +// US 1967 2006 Oct lastSun 2:00 0 S +// US 1967 1973 Apr lastSun 2:00 1:00 D +// US 1974 only Jan 6 2:00 1:00 D +// US 1975 only Feb 23 2:00 1:00 D +// US 1976 1986 Apr lastSun 2:00 1:00 D +// US 1987 2006 Apr Sun>=1 2:00 1:00 D +// US 2007 max Mar Sun>=8 2:00 1:00 D +// US 2007 max Nov Sun>=1 2:00 0 S + + +// When 2040 is mapped to 1984, the old U.S. rules are applied, i.e. DST isn't +// yet observed on March 31. If mapped to 2012, the new U.S. rules are applied +// and DST is already observed, which is the expected behaviour. +// A similar effect is visible in November. +// NOTE: This test expects that 2012 and 2040 use the same DST rules. If this +// ever changes, the test needs to be updated accordingly. +{ + let dt1 = new Date(2040, Month.March, 31); + assertDateTime(dt1, "Sat Mar 31 2040 00:00:00 GMT-0700 (PDT)", "Pacific Daylight Time"); + + let dt2 = new Date(2040, Month.November, 1); + assertDateTime(dt2, "Thu Nov 01 2040 00:00:00 GMT-0700 (PDT)", "Pacific Daylight Time"); +} + +// 2038 is mapped to 2027 instead of 1971. +{ + let dt1 = new Date(2038, Month.March, 31); + assertDateTime(dt1, "Wed Mar 31 2038 00:00:00 GMT-0700 (PDT)", "Pacific Daylight Time"); + + let dt2 = new Date(2038, Month.November, 1); + assertDateTime(dt2, "Mon Nov 01 2038 00:00:00 GMT-0700 (PDT)", "Pacific Daylight Time"); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/time-zone-etc_localetime.js b/js/src/tests/non262/Date/time-zone-etc_localetime.js new file mode 100644 index 0000000000..eaf8f7d940 --- /dev/null +++ b/js/src/tests/non262/Date/time-zone-etc_localetime.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(xulRuntime.OS=="WINNT"||!xulRuntime.shell) + +assertEq(/^(PST|PDT)$/.test(getTimeZone()), true, + "The default time zone is set to PST8PDT for all jstests (when run in the shell)"); + +function timeZoneName() { + var dtf = new Intl.DateTimeFormat("en-US", {timeZoneName: "long"}); + return dtf.formatToParts().filter(x => x.type === "timeZoneName")[0].value; +} + +// Calling setTimeZone() with an undefined argument clears the TZ environment +// variable and by that reveal the actual system time zone. +setTimeZone(undefined); +var systemTimeZone = getTimeZone(); +var systemTimeZoneName = timeZoneName(); + +// Set to an unlikely system time zone, so that the next call to setTimeZone() +// will lead to a time zone change. +setTimeZone("Antarctica/Troll"); + +// Now call with the file path ":/etc/localtime" which is special-cased in +// DateTimeInfo to read the system time zone. +setTimeZone(":/etc/localtime"); + +assertEq(getTimeZone(), systemTimeZone); +assertEq(timeZoneName(), systemTimeZoneName); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/time-zone-path.js b/js/src/tests/non262/Date/time-zone-path.js new file mode 100644 index 0000000000..0181093bac --- /dev/null +++ b/js/src/tests/non262/Date/time-zone-path.js @@ -0,0 +1,56 @@ +// |reftest| skip-if(xulRuntime.OS=="WINNT"||!xulRuntime.shell||!this.hasOwnProperty("Intl")) + +assertEq(/^(PST|PDT)$/.test(getTimeZone()), true, + "The default time zone is set to PST8PDT for all jstests (when run in the shell)"); + +function timeZoneName() { + var dtf = new Intl.DateTimeFormat("en-US", {timeZoneName: "long"}); + return dtf.formatToParts(Date.UTC(2017, 2, 31, 12, 0, 0)).filter(x => x.type === "timeZoneName")[0].value; +} + +setTimeZone("Europe/Paris"); +assertEq(timeZoneName(), "Central European Summer Time"); + +setTimeZone(":Europe/Helsinki"); +assertEq(timeZoneName(), "Eastern European Summer Time"); + +setTimeZone("/zoneinfo/America/Chicago"); +assertEq(timeZoneName(), "Central Daylight Time"); + +setTimeZone("/this-part-is-ignored/zoneinfo/America/Chicago"); +assertEq(timeZoneName(), "Central Daylight Time"); + +setTimeZone(":/this-part-is-ignored/zoneinfo/America/Phoenix"); +assertEq(timeZoneName(), "Mountain Standard Time"); + +const invalidTimeZones = [ + // Non-existent timezone + "foo", + "/zoneinfo/foo", + "/zoneinfo/", + + // Not capitalized + "america/chicago", + + // No leading / + "zoneinfo/America/Chicago", + "foo/zoneinfo/America/Chicago", + ":zoneinfo/America/Chicago", + ":foo/zoneinfo/America/Chicago", + + // Path without "/zoneinfo/" + "/foo/America/Chicago", + ":/foo/America/Chicago", + + // Two colons + "::Europe/London", + "::/zoneinfo/America/Los_Angeles", + "::/this-part-is-ignored/zoneinfo/America/Los_Angeles", +]; + +for (const invalid of invalidTimeZones) { + assertThrowsInstanceOf(() => setTimeZone(invalid), Error); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/time-zone-pst.js b/js/src/tests/non262/Date/time-zone-pst.js new file mode 100644 index 0000000000..341d3c8236 --- /dev/null +++ b/js/src/tests/non262/Date/time-zone-pst.js @@ -0,0 +1,120 @@ +// |reftest| skip-if(!xulRuntime.shell) + +assertEq(/^(PST|PDT)$/.test(getTimeZone()), true, + "The default time zone is set to PST8PDT for all jstests (when run in the shell)"); + +const msPerMinute = 60 * 1000; + +function shortTimeZone(str) { + return str.replace("(Pacific Standard Time)", "(PST)") + .replace("(Pacific Daylight Time)", "(PDT)"); +} + +function assertEqDate(dt, date, time) { + assertEq(shortTimeZone(dt.toString()), `${date} ${time}`); + assertEq(dt.toDateString(), date); + assertEq(shortTimeZone(dt.toTimeString()), time); +} + +// PDT -> PST, using milliseconds from epoch. +{ + let midnight = new Date(2016, Month.November, 6, 0, 0, 0, 0); + let midnightUTC = Date.UTC(2016, Month.November, 6, 0, 0, 0, 0); + + // Ensure midnight time is correct. + assertEq(midnightUTC - midnight.getTime(), -7 * msPerHour); + + let tests = [ + { offset: 0 * 60, date: "Sun Nov 06 2016", time: "00:00:00 GMT-0700 (PDT)" }, + { offset: 0 * 60 + 30, date: "Sun Nov 06 2016", time: "00:30:00 GMT-0700 (PDT)" }, + { offset: 1 * 60, date: "Sun Nov 06 2016", time: "01:00:00 GMT-0700 (PDT)" }, + { offset: 1 * 60 + 30, date: "Sun Nov 06 2016", time: "01:30:00 GMT-0700 (PDT)" }, + { offset: 2 * 60, date: "Sun Nov 06 2016", time: "01:00:00 GMT-0800 (PST)" }, + { offset: 2 * 60 + 30, date: "Sun Nov 06 2016", time: "01:30:00 GMT-0800 (PST)" }, + { offset: 3 * 60, date: "Sun Nov 06 2016", time: "02:00:00 GMT-0800 (PST)" }, + { offset: 3 * 60 + 30, date: "Sun Nov 06 2016", time: "02:30:00 GMT-0800 (PST)" }, + { offset: 4 * 60, date: "Sun Nov 06 2016", time: "03:00:00 GMT-0800 (PST)" }, + { offset: 4 * 60 + 30, date: "Sun Nov 06 2016", time: "03:30:00 GMT-0800 (PST)" }, + ]; + + for (let {offset, date, time} of tests) { + let dt = new Date(midnight.getTime() + offset * msPerMinute); + assertEqDate(dt, date, time); + } +} + + +// PDT -> PST, using local date-time. +{ + let tests = [ + { offset: 0 * 60, date: "Sun Nov 06 2016", time: "00:00:00 GMT-0700 (PDT)" }, + { offset: 0 * 60 + 30, date: "Sun Nov 06 2016", time: "00:30:00 GMT-0700 (PDT)" }, + { offset: 1 * 60, date: "Sun Nov 06 2016", time: "01:00:00 GMT-0700 (PDT)" }, + { offset: 1 * 60 + 30, date: "Sun Nov 06 2016", time: "01:30:00 GMT-0700 (PDT)" }, + { offset: 2 * 60, date: "Sun Nov 06 2016", time: "02:00:00 GMT-0800 (PST)" }, + { offset: 2 * 60 + 30, date: "Sun Nov 06 2016", time: "02:30:00 GMT-0800 (PST)" }, + { offset: 3 * 60, date: "Sun Nov 06 2016", time: "03:00:00 GMT-0800 (PST)" }, + { offset: 3 * 60 + 30, date: "Sun Nov 06 2016", time: "03:30:00 GMT-0800 (PST)" }, + { offset: 4 * 60, date: "Sun Nov 06 2016", time: "04:00:00 GMT-0800 (PST)" }, + { offset: 4 * 60 + 30, date: "Sun Nov 06 2016", time: "04:30:00 GMT-0800 (PST)" }, + ]; + + for (let {offset, date, time} of tests) { + let dt = new Date(2016, Month.November, 6, (offset / 60)|0, (offset % 60), 0, 0); + assertEqDate(dt, date, time); + } +} + + +// PST -> PDT, using milliseconds from epoch. +{ + let midnight = new Date(2016, Month.March, 13, 0, 0, 0, 0); + let midnightUTC = Date.UTC(2016, Month.March, 13, 0, 0, 0, 0); + + // Ensure midnight time is correct. + assertEq(midnightUTC - midnight.getTime(), -8 * msPerHour); + + let tests = [ + { offset: 0 * 60, date: "Sun Mar 13 2016", time: "00:00:00 GMT-0800 (PST)" }, + { offset: 0 * 60 + 30, date: "Sun Mar 13 2016", time: "00:30:00 GMT-0800 (PST)" }, + { offset: 1 * 60, date: "Sun Mar 13 2016", time: "01:00:00 GMT-0800 (PST)" }, + { offset: 1 * 60 + 30, date: "Sun Mar 13 2016", time: "01:30:00 GMT-0800 (PST)" }, + { offset: 2 * 60, date: "Sun Mar 13 2016", time: "03:00:00 GMT-0700 (PDT)" }, + { offset: 2 * 60 + 30, date: "Sun Mar 13 2016", time: "03:30:00 GMT-0700 (PDT)" }, + { offset: 3 * 60, date: "Sun Mar 13 2016", time: "04:00:00 GMT-0700 (PDT)" }, + { offset: 3 * 60 + 30, date: "Sun Mar 13 2016", time: "04:30:00 GMT-0700 (PDT)" }, + { offset: 4 * 60, date: "Sun Mar 13 2016", time: "05:00:00 GMT-0700 (PDT)" }, + { offset: 4 * 60 + 30, date: "Sun Mar 13 2016", time: "05:30:00 GMT-0700 (PDT)" }, + ]; + + for (let {offset, date, time} of tests) { + let dt = new Date(midnight.getTime() + offset * msPerMinute); + assertEqDate(dt, date, time); + } +} + + +// PST -> PDT, using local date-time. +{ + let tests = [ + { offset: 0 * 60, date: "Sun Mar 13 2016", time: "00:00:00 GMT-0800 (PST)" }, + { offset: 0 * 60 + 30, date: "Sun Mar 13 2016", time: "00:30:00 GMT-0800 (PST)" }, + { offset: 1 * 60, date: "Sun Mar 13 2016", time: "01:00:00 GMT-0800 (PST)" }, + { offset: 1 * 60 + 30, date: "Sun Mar 13 2016", time: "01:30:00 GMT-0800 (PST)" }, + { offset: 2 * 60, date: "Sun Mar 13 2016", time: "03:00:00 GMT-0700 (PDT)" }, + { offset: 2 * 60 + 30, date: "Sun Mar 13 2016", time: "03:30:00 GMT-0700 (PDT)" }, + { offset: 3 * 60, date: "Sun Mar 13 2016", time: "03:00:00 GMT-0700 (PDT)" }, + { offset: 3 * 60 + 30, date: "Sun Mar 13 2016", time: "03:30:00 GMT-0700 (PDT)" }, + { offset: 4 * 60, date: "Sun Mar 13 2016", time: "04:00:00 GMT-0700 (PDT)" }, + { offset: 4 * 60 + 30, date: "Sun Mar 13 2016", time: "04:30:00 GMT-0700 (PDT)" }, + ]; + + for (let {offset, date, time} of tests) { + let dt = new Date(2016, Month.March, 13, (offset / 60)|0, (offset % 60), 0, 0); + assertEqDate(dt, date, time); + } +} + + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/time-zones-historic.js b/js/src/tests/non262/Date/time-zones-historic.js new file mode 100644 index 0000000000..3117870687 --- /dev/null +++ b/js/src/tests/non262/Date/time-zones-historic.js @@ -0,0 +1,538 @@ +// |reftest| skip-if(xulRuntime.OS=="WINNT"||!this.hasOwnProperty("Intl")) -- Windows doesn't accept IANA names for the TZ env variable; Requires ICU time zone support + +// bug 487897 +inTimeZone("Europe/London", () => { + let dt1 = new Date(1970, Month.January, 1, 0, 0, 0, 0); + assertDateTime(dt1, "Thu Jan 01 1970 00:00:00 GMT+0100 (Greenwich Mean Time)"); + assertEq(dt1.getHours(), 0); + + let dt2 = new Date(1915, Month.January, 1); + assertDateTime(dt2, "Fri Jan 01 1915 00:00:00 GMT+0000 (Greenwich Mean Time)"); + + let dt3 = new Date(1970, Month.January, 1); + assertDateTime(dt3, "Thu Jan 01 1970 00:00:00 GMT+0100 (Greenwich Mean Time)"); +}); + +// bug 637244 +inTimeZone("Asia/Novosibirsk", () => { + let dt1 = new Date("1942-03-01T00:00:00"); + assertDateTime(dt1, "Sun Mar 01 1942 00:00:00 GMT+0700 (Novosibirsk Standard Time)"); + dt1.setMonth(Month.April); + assertDateTime(dt1, "Wed Apr 01 1942 00:00:00 GMT+0700 (Novosibirsk Standard Time)"); + + let dt2 = new Date(2010, Month.October, 31); + assertDateTime(dt2, "Sun Oct 31 2010 00:00:00 GMT+0700 (Novosibirsk Summer Time)"); + dt2.setMonth(Month.November); + assertDateTime(dt2, "Wed Dec 01 2010 00:00:00 GMT+0600 (Novosibirsk Standard Time)"); + + let dt3 = new Date(1942, Month.April, 1); + assertDateTime(dt3, "Wed Apr 01 1942 00:00:00 GMT+0700 (Novosibirsk Standard Time)"); + + function getNumberOfDaysInMonth(year, month) { + switch (month) { + case Month.January: + case Month.March: + case Month.May: + case Month.July: + case Month.August: + case Month.October: + case Month.December: + return 31; + case Month.April: + case Month.June: + case Month.September: + case Month.November: + return 30; + case Month.February: + if (year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0)) + return 29; + return 28; + } + throw new Error(`Illegal month value: ${month}`); + } + + for (let year = 1900; year <= 2142; ++year) { + for (let month = Month.January; month <= Month.December; ++month) { + const numDays = getNumberOfDaysInMonth(year, month); + for (let day = 1; day <= numDays; ++day) { + let date = new Date(year, month, day); + assertEq(date.getMonth(), month); + } + } + } + + let dt4 = new Date(1984, Month.April, 1); + assertDateTime(dt4, "Sun Apr 01 1984 01:00:00 GMT+0800 (Novosibirsk Summer Time)"); + + let dt5 = new Date(1984, Month.March, 1); + assertDateTime(dt5, "Thu Mar 01 1984 00:00:00 GMT+0700 (Novosibirsk Standard Time)"); + + let dt6 = new Date(1984, Month.April, 1); + assertEq(dt6.toUTCString(), "Sat, 31 Mar 1984 17:00:00 GMT"); + assertEq(dt6.getTime(), 449600400000); +}); +inTimeZone("Europe/Tallinn", () => { + let dt = new Date(2040, Month.March, 31, 20); + + for (let {datetime, date, hours} of [ + {datetime: "Sat Mar 31 2040 20:00:00", date: 31, hours: 20}, + {datetime: "Sat Mar 31 2040 22:00:00", date: 31, hours: 22}, + {datetime: "Sun Apr 01 2040 00:00:00", date: 1, hours: 0}, + {datetime: "Sun Apr 01 2040 02:00:00", date: 1, hours: 2}, + {datetime: "Sun Apr 01 2040 04:00:00", date: 1, hours: 4}, + {datetime: "Sun Apr 01 2040 06:00:00", date: 1, hours: 6}, + {datetime: "Sun Apr 01 2040 08:00:00", date: 1, hours: 8}, + ]) { + assertDateTime(dt, `${datetime} GMT+0300 (Eastern European Summer Time)`); + assertEq(dt.getDate(), date); + assertEq(dt.getHours(), hours); + assertEq(dt.getTimezoneOffset(), -180); + + dt.setHours(dt.getHours() + 2); + } +}); +inTimeZone("Europe/Riga", () => { + let dt1 = new Date(2016, Month.March, 27, 2, 59); + assertDateTime(dt1, "Sun Mar 27 2016 02:59:00 GMT+0200 (Eastern European Standard Time)"); + + let dt2 = new Date(2016, Month.March, 27, 3, 0); + assertDateTime(dt2, "Sun Mar 27 2016 04:00:00 GMT+0300 (Eastern European Summer Time)"); +}); + +// bug 704486 +inTimeZone("Europe/Zagreb", () => { + let dt = new Date(Date.UTC(1942, Month.June, 11, 22, 0, 0, 0)); + assertDateTime(dt, "Fri Jun 12 1942 00:00:00 GMT+0200 (Central European Summer Time)"); + assertEq(dt.getFullYear(), 1942); + assertEq(dt.getMonth(), Month.June); + assertEq(dt.getDate(), 12); + assertEq(dt.getHours(), 0); + assertEq(dt.getMinutes(), 0); + assertEq(dt.getSeconds(), 0); + assertEq(dt.getMilliseconds(), 0); + assertEq(dt.getTimezoneOffset(), -120); +}); + +// bug 935909 +inTimeZone("Europe/London", () => { + let dt1 = new Date(1954, Month.January, 1); + assertDateTime(dt1, "Fri Jan 01 1954 00:00:00 GMT+0000 (Greenwich Mean Time)"); + + let dt2 = new Date(1965, Month.January, 1); + assertDateTime(dt2, "Fri Jan 01 1965 00:00:00 GMT+0000 (Greenwich Mean Time)"); + + let dt3 = new Date(1970, Month.January, 1); + assertDateTime(dt3, "Thu Jan 01 1970 00:00:00 GMT+0100 (Greenwich Mean Time)"); + + let dt4 = new Date(-504921600000); + assertDateTime(dt4, "Fri Jan 01 1954 00:00:00 GMT+0000 (Greenwich Mean Time)"); + + let dt5 = new Date(1974, Month.January, 1); + assertDateTime(dt5, "Tue Jan 01 1974 00:00:00 GMT+0000 (Greenwich Mean Time)"); +}); +inTimeZone("Europe/Dublin", () => { + let dt = new Date(0, Month.January, 1, 0, 0, 0, 0); + dt.setFullYear(1970); + assertEq(dt.getFullYear(), 1970); +}); + +// bug 937261 +inTimeZone("Europe/Lisbon", () => { + let dt = new Date(0, Month.January, 1, 0, 0, 0, 0); + assertDateTime(dt, "Mon Jan 01 1900 00:00:00 GMT-0036 (Western European Standard Time)"); + + dt.setFullYear(2015); + assertDateTime(dt, "Thu Jan 01 2015 00:00:00 GMT+0000 (Western European Standard Time)"); + + dt.setMonth(Month.November); + assertDateTime(dt, "Sun Nov 01 2015 00:00:00 GMT+0000 (Western European Standard Time)"); +}); +inTimeZone("Europe/London", () => { + let dt = new Date(0, Month.January, 1, 0, 0, 0, 0); + assertDateTime(dt, "Mon Jan 01 1900 00:00:00 GMT+0000 (Greenwich Mean Time)"); + + dt.setFullYear(2015); + assertDateTime(dt, "Thu Jan 01 2015 00:00:00 GMT+0000 (Greenwich Mean Time)"); + + dt.setMonth(Month.November); + assertDateTime(dt, "Sun Nov 01 2015 00:00:00 GMT+0000 (Greenwich Mean Time)"); +}); + +// bug 1079720 +inTimeZone("Europe/Moscow", () => { + let dt1 = new Date(2014, Month.January, 1); + assertDateTime(dt1, "Wed Jan 01 2014 00:00:00 GMT+0400 (Moscow Standard Time)"); + assertEq(dt1.toISOString(), "2013-12-31T20:00:00.000Z"); + assertEq(dt1.getHours(), 0); + + let dt2 = new Date(2013, Month.January, 1); + assertDateTime(dt2, "Tue Jan 01 2013 00:00:00 GMT+0400 (Moscow Standard Time)"); + + let dt3 = new Date(new Date(2014, Month.December, 1).setMonth(Month.January)); + assertDateTime(dt3, "Wed Jan 01 2014 00:00:00 GMT+0400 (Moscow Standard Time)"); + assertEq(dt3.getFullYear(), 2014); + + let dt4 = new Date(2040, Month.April, 1); + assertDateTime(dt4, "Sun Apr 01 2040 00:00:00 GMT+0300 (Moscow Standard Time)"); + + let dt5 = new Date(2043, Month.April, 1); + assertDateTime(dt5, "Wed Apr 01 2043 00:00:00 GMT+0300 (Moscow Standard Time)"); + + let dt6 = new Date(2054, Month.April, 1); + assertDateTime(dt6, "Wed Apr 01 2054 00:00:00 GMT+0300 (Moscow Standard Time)"); + + let dt7 = new Date(2065, Month.April, 1); + assertDateTime(dt7, "Wed Apr 01 2065 00:00:00 GMT+0300 (Moscow Standard Time)"); + + let dt8 = new Date(2068, Month.April, 1); + assertDateTime(dt8, "Sun Apr 01 2068 00:00:00 GMT+0300 (Moscow Standard Time)"); + + let dt9 = new Date(2071, Month.April, 1); + assertDateTime(dt9, "Wed Apr 01 2071 00:00:00 GMT+0300 (Moscow Standard Time)"); + + let dt10 = new Date(2082, Month.April, 1); + assertDateTime(dt10, "Wed Apr 01 2082 00:00:00 GMT+0300 (Moscow Standard Time)"); + + let dt11 = new Date(2093, Month.April, 1); + assertDateTime(dt11, "Wed Apr 01 2093 00:00:00 GMT+0300 (Moscow Standard Time)"); + + let dt12 = new Date(2096, Month.April, 1); + assertDateTime(dt12, "Sun Apr 01 2096 00:00:00 GMT+0300 (Moscow Standard Time)"); + + let dt13 = new Date(2099, Month.April, 1); + assertDateTime(dt13, "Wed Apr 01 2099 00:00:00 GMT+0300 (Moscow Standard Time)"); +}); + +// bug 1107837 +inTimeZone("Europe/Moscow", () => { + let dt1 = new Date(2015, Month.January, 4); + assertDateTime(dt1, "Sun Jan 04 2015 00:00:00 GMT+0300 (Moscow Standard Time)"); + + let dt2 = new Date(2015, Month.January, 5); + assertDateTime(dt2, "Mon Jan 05 2015 00:00:00 GMT+0300 (Moscow Standard Time)"); + + let dt3 = new Date(2015, Month.January, 6); + assertDateTime(dt3, "Tue Jan 06 2015 00:00:00 GMT+0300 (Moscow Standard Time)"); + + let dt4 = new Date(2015, Month.January, 7); + assertDateTime(dt4, "Wed Jan 07 2015 00:00:00 GMT+0300 (Moscow Standard Time)"); + + let dt5 = new Date(2015, Month.January, 8); + assertDateTime(dt5, "Thu Jan 08 2015 00:00:00 GMT+0300 (Moscow Standard Time)"); + + let dt6 = new Date(2015, Month.January, 9); + assertDateTime(dt6, "Fri Jan 09 2015 00:00:00 GMT+0300 (Moscow Standard Time)"); +}); + +// bug 1122571 +inTimeZone("Europe/Berlin", () => { + const locale = "en-001"; + const opts = {timeZoneName: "long", hour12: false}; + + let dt1 = new Date(1950, Month.March, 28); + assertDateTime(dt1, "Tue Mar 28 1950 00:00:00 GMT+0100 (Central European Standard Time)"); + assertEq(dt1.toLocaleString(locale, opts), "28/03/1950, 00:00:00 GMT+01:00"); + + let dt2 = new Date(1950, Month.July, 1); + assertDateTime(dt2, "Sat Jul 01 1950 00:00:00 GMT+0100 (Central European Standard Time)"); + assertEq(dt2.toLocaleString(locale, opts), "01/07/1950, 00:00:00 GMT+01:00"); + + let dt3 = new Date(1960, Month.March, 27); + assertDateTime(dt3, "Sun Mar 27 1960 00:00:00 GMT+0100 (Central European Standard Time)"); + assertEq(dt3.toLocaleString(locale, opts), "27/03/1960, 00:00:00 GMT+01:00"); + + let dt4 = new Date(1960, Month.March, 28); + assertDateTime(dt4, "Mon Mar 28 1960 00:00:00 GMT+0100 (Central European Standard Time)"); + assertEq(dt4.toLocaleString(locale, opts), "28/03/1960, 00:00:00 GMT+01:00"); + + let dt5 = new Date(1960, Month.March, 29); + assertDateTime(dt5, "Tue Mar 29 1960 00:00:00 GMT+0100 (Central European Standard Time)"); + assertEq(dt5.toLocaleString(locale, opts), "29/03/1960, 00:00:00 GMT+01:00"); + + let dt6 = new Date(1960, Month.July, 1); + assertDateTime(dt6, "Fri Jul 01 1960 00:00:00 GMT+0100 (Central European Standard Time)"); + assertEq(dt6.toLocaleString(locale, opts), "01/07/1960, 00:00:00 GMT+01:00"); + + let dt7 = new Date(1961, Month.July, 1); + assertDateTime(dt7, "Sat Jul 01 1961 00:00:00 GMT+0100 (Central European Standard Time)"); + assertEq(dt7.toLocaleString(locale, opts), "01/07/1961, 00:00:00 GMT+01:00"); + + let dt8 = new Date(1970, Month.March, 1); + assertDateTime(dt8, "Sun Mar 01 1970 00:00:00 GMT+0100 (Central European Standard Time)"); + assertEq(dt8.toLocaleString(locale, opts), "01/03/1970, 00:00:00 Central European Standard Time"); + + let dt9 = new Date(1970, Month.March, 27); + assertDateTime(dt9, "Fri Mar 27 1970 00:00:00 GMT+0100 (Central European Standard Time)"); + assertEq(dt9.toLocaleString(locale, opts), "27/03/1970, 00:00:00 Central European Standard Time"); + + let dt10 = new Date(1970, Month.March, 28); + assertDateTime(dt10, "Sat Mar 28 1970 00:00:00 GMT+0100 (Central European Standard Time)"); + assertEq(dt10.toLocaleString(locale, opts), "28/03/1970, 00:00:00 Central European Standard Time"); + + let dt11 = new Date(1970, Month.July, 1); + assertDateTime(dt11, "Wed Jul 01 1970 00:00:00 GMT+0100 (Central European Standard Time)"); + assertEq(dt11.toLocaleString(locale, opts), "01/07/1970, 00:00:00 Central European Standard Time"); +}); + +// bug 1143398 +inTimeZone("Australia/Adelaide", () => { + let dt = new Date(621000); + assertDateTime(dt, "Thu Jan 01 1970 09:40:21 GMT+0930 (Australian Central Standard Time)"); + assertEq(dt.getUTCFullYear(), 1970); + + dt.setMilliseconds(dt.getMilliseconds()); + dt.setSeconds(dt.getSeconds()); + + assertDateTime(dt, "Thu Jan 01 1970 09:40:21 GMT+0930 (Australian Central Standard Time)"); + assertEq(dt.getUTCFullYear(), 1970); +}); +inTimeZone("America/Denver", () => { + let dt = new Date(1446361200000); + assertDateTime(dt, "Sun Nov 01 2015 01:00:00 GMT-0600 (Mountain Daylight Time)"); + + assertEq(dt.getTime(), 1446361200000); + dt.setMilliseconds(0); + assertEq(dt.getTime(), 1446361200000); +}); + +// bug 1233809 +inTimeZone("America/New_York", () => { + let dt = new Date(1980, Month.March, 10); + assertDateTime(dt, "Mon Mar 10 1980 00:00:00 GMT-0500 (Eastern Standard Time)"); +}); + +// bug 1254041 +inTimeZone("Asia/Ho_Chi_Minh", () => { + let dt1 = new Date(Date.UTC(1969, Month.December, 31, 23, 0)); + assertDateTime(dt1, "Thu Jan 01 1970 07:00:00 GMT+0800 (Indochina Time)"); + assertEq(dt1.getTime(), -3600000); + + dt1.setMinutes(dt1.getMinutes() + 30); + assertDateTime(dt1, "Thu Jan 01 1970 07:30:00 GMT+0800 (Indochina Time)"); + assertEq(dt1.getTime(), -1800000); + + dt1.setMinutes(dt1.getMinutes() + 30); + assertDateTime(dt1, "Thu Jan 01 1970 08:00:00 GMT+0800 (Indochina Time)"); + assertEq(dt1.getTime(), 0); + + dt1.setMinutes(dt1.getMinutes() + 30); + assertDateTime(dt1, "Thu Jan 01 1970 08:30:00 GMT+0800 (Indochina Time)"); + assertEq(dt1.getTime(), 1800000); + + dt1.setMinutes(dt1.getMinutes() + 30); + assertDateTime(dt1, "Thu Jan 01 1970 09:00:00 GMT+0800 (Indochina Time)"); + assertEq(dt1.getTime(), 3600000); + + let dt2 = new Date(-1); + assertEq(dt2.getTime(), -1); + + dt2.setMilliseconds(dt2.getMilliseconds() + 1); + assertEq(dt2.getTime(), 0); + + dt2.setTime(1); + assertEq(dt2.getTime(), 1); + + dt2.setMilliseconds(dt2.getMilliseconds() - 1); + assertEq(dt2.getTime(), 0); + + dt2.setMilliseconds(dt2.getMilliseconds() - 1); + assertEq(dt2.getTime(), -1); + + dt2.setMilliseconds(dt2.getMilliseconds() + 1); + assertEq(dt2.getTime(), 0); + + dt2.setMilliseconds(dt2.getMilliseconds() + 3600000); + assertEq(dt2.getTime(), 3600000); + + dt2.setMilliseconds(dt2.getMilliseconds() + (3600000 * 2 - 1)); + assertEq(dt2.getTime(), 3600000 * 3 - 1); + + dt2.setMilliseconds(dt2.getMilliseconds() + 1); + assertEq(dt2.getTime(), 3600000 * 3); + + dt2.setMilliseconds(dt2.getMilliseconds() + (3600000 * 2)); + assertEq(dt2.getTime(), 3600000 * 5); + + let dt3 = new Date(0); + assertDateTime(dt3, "Thu Jan 01 1970 08:00:00 GMT+0800 (Indochina Time)"); + + let dt4 = new Date(-1); + assertDateTime(dt4, "Thu Jan 01 1970 07:59:59 GMT+0800 (Indochina Time)"); +}); + +// bug 1300197 +inTimeZone("Europe/Dublin", () => { + let dt = new Date(1910, Month.January, 1); + assertDateTime(dt, "Sat Jan 01 1910 00:00:00 GMT-0025 (Greenwich Mean Time)"); +}); + +// bug 1304774 +inTimeZone("Europe/Zurich", () => { + let dt = new Date(1986, Month.April, 4, 0, 0, 0, 0); + assertDateTime(dt, "Fri Apr 04 1986 00:00:00 GMT+0200 (Central European Summer Time)"); + assertEq(dt.getTimezoneOffset(), -120); +}); + +// bug 1330307 +inTimeZone("Europe/Moscow", () => { + let dt = new Date(2012, Month.May, 14, 12, 13, 14); + assertDateTime(dt, "Mon May 14 2012 12:13:14 GMT+0400 (Moscow Standard Time)"); + + let dtf = new Intl.DateTimeFormat("en-US", {hour: "numeric", minute: "numeric"}); + assertEq(dtf.format(dt), "12:13 PM"); +}); +inTimeZone("Asia/Baku", () => { + let dt = new Date(2012, Month.May, 14, 12, 13, 14); + assertDateTime(dt, "Mon May 14 2012 12:13:14 GMT+0500 (Azerbaijan Summer Time)"); + + let dtf = new Intl.DateTimeFormat("en-US", {hour: "numeric", minute: "numeric"}); + assertEq(dtf.format(dt), "12:13 PM"); +}); +inTimeZone("Asia/Tbilisi", () => { + let dt = new Date(2012, Month.May, 14, 12, 13, 14); + assertDateTime(dt, "Mon May 14 2012 12:13:14 GMT+0400 (Georgia Standard Time)"); + + let dtf = new Intl.DateTimeFormat("en-US", {hour: "numeric", minute: "numeric"}); + assertEq(dtf.format(dt), "12:13 PM"); +}); + +// bug 1335818 +inTimeZone("Asia/Jerusalem", () => { + let dt1 = new Date(2013, Month.March, 22, 1, 0, 0, 0); + assertDateTime(dt1, "Fri Mar 22 2013 01:00:00 GMT+0200 (Israel Standard Time)"); + + let dt2 = new Date(2013, Month.March, 22, 2, 0, 0, 0); + assertDateTime(dt2, "Fri Mar 22 2013 02:00:00 GMT+0200 (Israel Standard Time)"); + + let dt3 = new Date(2013, Month.March, 22, 3, 0, 0, 0); + assertDateTime(dt3, "Fri Mar 22 2013 03:00:00 GMT+0200 (Israel Standard Time)"); + + let dt4 = new Date(2013, Month.March, 29, 1, 0, 0, 0); + assertDateTime(dt4, "Fri Mar 29 2013 01:00:00 GMT+0200 (Israel Standard Time)"); + + let dt5 = new Date(2013, Month.March, 29, 2, 0, 0, 0); + assertDateTime(dt5, "Fri Mar 29 2013 03:00:00 GMT+0300 (Israel Daylight Time)"); + + let dt6 = new Date(2013, Month.March, 29, 3, 0, 0, 0); + assertDateTime(dt6, "Fri Mar 29 2013 03:00:00 GMT+0300 (Israel Daylight Time)"); +}); + +// bug 1342853 +inTimeZone("America/Sao_Paulo", () => { + let dt1 = new Date(2017, Month.October, 14, 12, 0, 0); + assertDateTime(dt1, "Sat Oct 14 2017 12:00:00 GMT-0300 (Brasilia Standard Time)"); + assertEq(dt1.getTimezoneOffset(), 180); + + let dt2 = new Date(2017, Month.October, 15, 12, 0, 0); + assertDateTime(dt2, "Sun Oct 15 2017 12:00:00 GMT-0200 (Brasilia Summer Time)"); + assertEq(dt2.getTimezoneOffset(), 120); + + let dt3 = new Date(2018, Month.February, 17, 12, 0, 0); + assertDateTime(dt3, "Sat Feb 17 2018 12:00:00 GMT-0200 (Brasilia Summer Time)"); + assertEq(dt3.getTimezoneOffset(), 120); + + let dt4 = new Date(2018, Month.February, 18, 12, 0, 0); + assertDateTime(dt4, "Sun Feb 18 2018 12:00:00 GMT-0300 (Brasilia Standard Time)"); + assertEq(dt4.getTimezoneOffset(), 180); + + let dt5 = new Date(2018, Month.November, 3, 12, 0, 0); + assertDateTime(dt5, "Sat Nov 03 2018 12:00:00 GMT-0300 (Brasilia Standard Time)"); + assertEq(dt5.getTimezoneOffset(), 180); + + let dt6 = new Date(2018, Month.November, 4, 12, 0, 0); + assertDateTime(dt6, "Sun Nov 04 2018 12:00:00 GMT-0200 (Brasilia Summer Time)"); + assertEq(dt6.getTimezoneOffset(), 120); + + let dt7 = new Date(2019, Month.February, 16, 12, 0, 0); + assertDateTime(dt7, "Sat Feb 16 2019 12:00:00 GMT-0200 (Brasilia Summer Time)"); + assertEq(dt7.getTimezoneOffset(), 120); + + let dt8 = new Date(2019, Month.February, 17, 12, 0, 0); + assertDateTime(dt8, "Sun Feb 17 2019 12:00:00 GMT-0300 (Brasilia Standard Time)"); + assertEq(dt8.getTimezoneOffset(), 180); +}); + +// bug 1365192 +inTimeZone("America/Asuncion", () => { + let dt = new Date(2018, Month.March, 31); + assertDateTime(dt, "Sat Mar 31 2018 00:00:00 GMT-0400 (Paraguay Standard Time)"); + assertEq(dt.getTimezoneOffset(), 240); +}); + +// bug 1385643 +inTimeZone("Europe/Warsaw", () => { + let shortMonths = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; + let dtf = new Intl.DateTimeFormat("en-US", {month: "short"}); + + for (let year = 1900; year <= 2100; ++year) { + for (let month = Month.January; month <= Month.December; ++month) { + let date = new Date(year, month, 1); + assertEq(dtf.format(date), shortMonths[month]); + } + } +}); + +// bug 1401696 +inTimeZone("Europe/Berlin", () => { + let dt = new Date(1970, Month.January, 1, 0, 0, 0); + assertDateTime(dt, "Thu Jan 01 1970 00:00:00 GMT+0100 (Central European Standard Time)"); +}); + +// bug 1459842 +inTimeZone("Europe/Moscow", () => { + let dt1 = new Date(1004, Month.April, 1, 2, 0, 0); + assertDateTime(dt1, "Sun Apr 01 1004 02:00:00 GMT+0230 (Moscow Standard Time)"); + assertEq(dt1.getHours(), 2); + + let dt2 = new Date(1004, Month.April, 1, 1, 0, 0); + assertDateTime(dt2, "Sun Apr 01 1004 01:00:00 GMT+0230 (Moscow Standard Time)"); + assertEq(dt2.getHours(), 1); + + let dt3 = new Date(1004, Month.April, 1, 0, 0, 0); + assertDateTime(dt3, "Sun Apr 01 1004 00:00:00 GMT+0230 (Moscow Standard Time)"); + assertEq(dt3.getHours(), 0); + + let dt4 = new Date(1004, Month.March, 1, 2, 0, 0); + assertDateTime(dt4, "Thu Mar 01 1004 02:00:00 GMT+0230 (Moscow Standard Time)"); + assertEq(dt4.getHours(), 2); + + let dt5 = new Date(1004, Month.March, 1, 1, 0, 0); + assertDateTime(dt5, "Thu Mar 01 1004 01:00:00 GMT+0230 (Moscow Standard Time)"); + assertEq(dt5.getHours(), 1); + + let dt6 = new Date(1004, Month.March, 1, 0, 0, 0); + assertDateTime(dt6, "Thu Mar 01 1004 00:00:00 GMT+0230 (Moscow Standard Time)"); + assertEq(dt6.getHours(), 0); + +}); + +// bug 1799638 +inTimeZone("Asia/Tokyo", () => { + let dt1 = new Date(1948, Month.May, 1, 23, 59, 59); + assertDateTime(dt1, "Sat May 01 1948 23:59:59 GMT+0900 (Japan Standard Time)"); + assertEq(dt1.getTimezoneOffset(), -540); + + let dt2 = new Date(1948, Month.May, 1, 24, 0, 0); + assertDateTime(dt2, "Sun May 02 1948 01:00:00 GMT+1000 (Japan Daylight Time)"); + assertEq(dt2.getTimezoneOffset(), -600); + + let dt3 = new Date(1948, Month.May, 1, 23, 59, 59, 1); + assertDateTime(dt3, "Sat May 01 1948 23:59:59 GMT+0900 (Japan Standard Time)"); + assertEq(dt3.getTimezoneOffset(), -540); +}); +inTimeZone("America/New_York", () => { + let dt1 = new Date(1966, Month.April, 24, 1, 59, 59); + assertDateTime(dt1, "Sun Apr 24 1966 01:59:59 GMT-0500 (Eastern Standard Time)"); + assertEq(dt1.getTimezoneOffset(), 300); + + let dt2 = new Date(1966, Month.April, 24, 2, 0, 0); + assertDateTime(dt2, "Sun Apr 24 1966 03:00:00 GMT-0400 (Eastern Daylight Time)"); + assertEq(dt2.getTimezoneOffset(), 240); + + let dt3 = new Date(1966, Month.April, 24, 1, 59, 59, 1); + assertDateTime(dt3, "Sun Apr 24 1966 01:59:59 GMT-0500 (Eastern Standard Time)"); + assertEq(dt3.getTimezoneOffset(), 300); +}); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/time-zones-imported.js b/js/src/tests/non262/Date/time-zones-imported.js new file mode 100644 index 0000000000..8a13e34981 --- /dev/null +++ b/js/src/tests/non262/Date/time-zones-imported.js @@ -0,0 +1,1020 @@ +// |reftest| skip-if(xulRuntime.OS=="WINNT"||!this.hasOwnProperty("Intl")) -- Windows doesn't accept IANA names for the TZ env variable; Requires ICU time zone support + +// Imported tests from es6draft and then adapted to use ICU/CLDR time zone display names. + +function assertSame(expected, actual, message = undefined) { + if (message !== undefined) + assertEq(actual, expected, String(message)); + else + assertEq(actual, expected); +} + +function assertTrue(actual, message = undefined) { + assertSame(true, actual, message); +} + +// File: lib/datetime.jsm +const { + DayOfWeek, + Month, + DateTime, + TimeZone, + Format, +} = (function() { + +// 5.2 Algorithm Conventions +function modulo(dividend, divisor) { + assertTrue(typeof dividend === "number"); + assertTrue(typeof divisor === "number"); + assertTrue(divisor !== 0 && Number.isFinite(divisor)); + let remainder = dividend % divisor; + // NB: add +0 to convert -0 to +0 + return (remainder >= 0 ? remainder + 0 : remainder + divisor); +} + +// 7.1.4 ToInteger ( argument ) +function ToInteger(number) { + /* steps 1-2 */ + assertTrue(typeof number === "number"); + /* step 3 */ + if (Number.isNaN(number)) + return +0.0; + /* step 4 */ + if (number == 0.0 || !Number.isFinite(number)) + return number; + /* step 5 */ + return Math.sign(number) * Math.floor(Math.abs(number)); +} + +// 20.3.1.2 Day Number and Time within Day +const msPerDay = 86400000; + +// 20.3.1.2 Day Number and Time within Day +function Day(t) { + assertTrue(typeof t === "number"); + return Math.floor(t / msPerDay); +} + +// 20.3.1.2 Day Number and Time within Day +function TimeWithinDay(t) { + assertTrue(typeof t === "number"); + return modulo(t, msPerDay); +} + +// 20.3.1.3 Year Number +function DaysInYear(y) { + assertTrue(typeof y === "number"); + if (y % 4 !== 0) { + return 365; + } + if (y % 100 !== 0) { + return 366; + } + if (y % 400 !== 0) { + return 365; + } + return 366; +} + +// 20.3.1.3 Year Number +function DayFromYear(y) { + assertTrue(typeof y === "number"); + return 365 * (y - 1970) + Math.floor((y - 1969) / 4) - Math.floor((y - 1901) / 100) + Math.floor((y - 1601) / 400); +} + +// 20.3.1.3 Year Number +function TimeFromYear(y) { + assertTrue(typeof y === "number"); + return msPerDay * DayFromYear(y); +} + +// TODO: fill in rest + +// 20.3.1.10 Hours, Minutes, Second, and Milliseconds +const HoursPerDay = 24; +const MinutesPerHour = 60; +const SecondsPerMinute = 60; +const msPerSecond = 1000; +const msPerMinute = msPerSecond * SecondsPerMinute; +const msPerHour = msPerMinute * MinutesPerHour; + +// 20.3.1.10 Hours, Minutes, Second, and Milliseconds +function HourFromTime(t) { + assertTrue(typeof t === "number"); + return modulo(Math.floor(t / msPerHour), HoursPerDay); +} + +// 20.3.1.10 Hours, Minutes, Second, and Milliseconds +function MinFromTime(t) { + assertTrue(typeof t === "number"); + return modulo(Math.floor(t / msPerMinute), MinutesPerHour); +} + +// 20.3.1.10 Hours, Minutes, Second, and Milliseconds +function SecFromTime(t) { + assertTrue(typeof t === "number"); + return modulo(Math.floor(t / msPerSecond), SecondsPerMinute); +} + +// 20.3.1.10 Hours, Minutes, Second, and Milliseconds +function msFromTime(t) { + assertTrue(typeof t === "number"); + return modulo(t, msPerSecond); +} + +// 20.3.1.11 MakeTime (hour, min, sec, ms) +function MakeTime(hour, min, sec, ms) { + assertTrue(typeof hour === "number"); + assertTrue(typeof min === "number"); + assertTrue(typeof sec === "number"); + assertTrue(typeof ms === "number"); + if (!Number.isFinite(hour) || !Number.isFinite(min) || !Number.isFinite(sec) || !Number.isFinite(ms)) { + return Number.NaN; + } + let h = ToInteger(hour); + let m = ToInteger(min); + let s = ToInteger(sec); + let milli = ToInteger(ms); + let t = h * msPerHour + m * msPerMinute + s * msPerSecond + milli; + return t; +} + +// 20.3.1.12 MakeDay (year, month, date) +function MakeDay(year, month, date) { + assertTrue(typeof year === "number"); + assertTrue(typeof month === "number"); + assertTrue(typeof date === "number"); + if (!Number.isFinite(year) || !Number.isFinite(month) || !Number.isFinite(date)) { + return Number.NaN; + } + let y = ToInteger(year); + let m = ToInteger(month); + let dt = ToInteger(date); + let ym = y + Math.floor(m / 12); + let mn = modulo(m, 12); + + const monthStart = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]; + let day = Math.floor(TimeFromYear(ym) / msPerDay) + monthStart[mn]; + if (mn >= 2 && DaysInYear(ym) == 366) { + day += 1; + } + + return day + dt - 1; +} + +// 20.3.1.13 MakeDate (day, time) +function MakeDate(day, time) { + assertTrue(typeof day === "number"); + assertTrue(typeof time === "number"); + if (!Number.isFinite(day) || !Number.isFinite(time)) { + return Number.NaN; + } + return day * msPerDay + time; +} + +// 20.3.1.14 TimeClip (time) +function TimeClip(time) { + assertTrue(typeof time === "number"); + if (!Number.isFinite(time)) { + return Number.NaN; + } + if (Math.abs(time) > 8.64e15) { + return Number.NaN; + } + return ToInteger(time) + (+0); +} + +const DayOfWeek = { + Sunday: 0, + Monday: 1, + Tuesday: 2, + Wednesday: 3, + Thursday: 4, + Friday: 5, + Saturday: 6, +}; + +const Month = { + January: 0, + February: 1, + March: 2, + April: 3, + May: 4, + June: 5, + July: 6, + August: 7, + September: 8, + October: 9, + November: 10, + December: 11, +}; + +const DateTime = { + Local: class { + constructor(year, month, day, weekday, hour = 0, minute = 0, second = 0, ms = 0) { + Object.assign(this, {year, month, day, weekday, hour, minute, second, ms}); + } + + toDate() { + return new Date(this.year, this.month, this.day, this.hour, this.minute, this.second, this.ms); + } + }, + UTC: class { + constructor(year, month, day, weekday, hour = 0, minute = 0, second = 0, ms = 0) { + Object.assign(this, {year, month, day, weekday, hour, minute, second, ms}); + } + + toInstant() { + return MakeDate(MakeDay(this.year, this.month, this.day), MakeTime(this.hour, this.minute, this.second, this.ms)); + } + }, +}; + +function TimeZone(hour, minute = 0, second = 0) { + return new class TimeZone { + constructor(hour, minute, second) { + Object.assign(this, {hour, minute, second}); + } + + toOffset() { + let offset = TimeZoneOffset(this.hour, this.minute, this.second); + return offset !== 0 ? -offset : 0; + } + }(hour, minute, second); + + function TimeZoneOffset(hour, minute = 0, second = 0) { + assertTrue(typeof hour === "number"); + assertTrue(typeof minute === "number"); + assertTrue(typeof second === "number"); + assertTrue(minute >= 0); + assertTrue(second >= 0); + if (hour < 0 || Object.is(-0, hour)) { + return hour * MinutesPerHour - minute - (second / 60); + } + return hour * MinutesPerHour + minute + (second / 60); + } +} + +const Format = { + Locale: "en-US", + DateTime: { + localeMatcher: "lookup", + timeZone: void 0, + weekday: "short", + era: void 0, + year: "numeric", + month: "2-digit", + day: "2-digit", + hour: "2-digit", + minute: "2-digit", + second: "2-digit", + timeZoneName: "short", + formatMatcher: "best fit", + hour12: void 0, + }, + Date: { + localeMatcher: "lookup", + timeZone: void 0, + weekday: "short", + era: void 0, + year: "numeric", + month: "2-digit", + day: "2-digit", + hour: void 0, + minute: void 0, + second: void 0, + timeZoneName: void 0, + formatMatcher: "best fit", + hour12: void 0, + }, + Time: { + localeMatcher: "lookup", + timeZone: void 0, + weekday: void 0, + era: void 0, + year: void 0, + month: void 0, + day: void 0, + hour: "2-digit", + minute: "2-digit", + second: "2-digit", + timeZoneName: "short", + formatMatcher: "best fit", + hour12: void 0, + }, +}; + +return { + DayOfWeek, + Month, + DateTime, + TimeZone, + Format, +}; +})(); + + +// File: lib/assert-datetime.js + +function assertDate(local, utc, timeZone, options, formatArgs) { + let d = local.toDate(); + assertDateValue(d, utc.toInstant(), timeZone.toOffset()); + assertLocalDate(d, local); + assertUTCDate(d, utc); + assertDateString(d, options, formatArgs); +} + +function assertDateValue(actual, dateValue, timeZoneOffset) { + assertSame(dateValue, actual.valueOf(), `valueOf()[${dateValue - actual.valueOf()}]`); + assertSame(dateValue, actual.getTime(), `valueOf()[${dateValue - actual.getTime()}]`); + assertSame(timeZoneOffset, actual.getTimezoneOffset(), "getTimezoneOffset()"); +} + +function assertLocalDate(actual, {year, month, day, weekday, hour = 0, minute = 0, second = 0, ms = 0}) { + assertSame(year, actual.getFullYear(), "getFullYear()"); + assertSame(month, actual.getMonth(), "getMonth()"); + assertSame(day, actual.getDate(), "getDate()"); + assertSame(weekday, actual.getDay(), "getDay()"); + assertSame(hour, actual.getHours(), "getHours()"); + assertSame(minute, actual.getMinutes(), "getMinutes()"); + assertSame(second, actual.getSeconds(), "getSeconds()"); + assertSame(ms, actual.getMilliseconds(), "getMilliseconds()"); +} + +function assertUTCDate(actual, {year, month, day, weekday, hour = 0, minute = 0, second = 0, ms = 0}) { + assertSame(year, actual.getUTCFullYear(), "getUTCFullYear()"); + assertSame(month, actual.getUTCMonth(), "getUTCMonth()"); + assertSame(day, actual.getUTCDate(), "getUTCDate()"); + assertSame(weekday, actual.getUTCDay(), "getUTCDay()"); + assertSame(hour, actual.getUTCHours(), "getUTCHours()"); + assertSame(minute, actual.getUTCMinutes(), "getUTCMinutes()"); + assertSame(second, actual.getUTCSeconds(), "getUTCSeconds()"); + assertSame(ms, actual.getUTCMilliseconds(), "getUTCMilliseconds()"); +} + +function assertDateString(actual, options, formatArgs = { + LocaleString: [Format.Locale, Format.DateTime], + LocaleDateString: [Format.Locale, Format.Date], + LocaleTimeString: [Format.Locale, Format.Time], +}) { + for (var key of Object.keys(options)) { + var args = formatArgs[key] || []; + assertSame(options[key], actual[`to${key}`](...args), `to${key}()`); + } +} + + +// File: Date/Africa_Monrovia.js +// Liberia was the last country to switch to UTC based offsets (1972 May). + +inTimeZone("Africa/Monrovia", () => { +{ + let local = new DateTime.Local(1972, Month.January, 6, DayOfWeek.Thursday, 0, 0, 0); + let utc = new DateTime.UTC(1972, Month.January, 6, DayOfWeek.Thursday, 0, 44, 30); + + assertDate(local, utc, TimeZone(-0,44,30), { + String: "Thu Jan 06 1972 00:00:00 GMT-0044 (Greenwich Mean Time)", + UTCString: "Thu, 06 Jan 1972 00:44:30 GMT", + }); +} + +{ + let local = new DateTime.Local(1972, Month.January, 6, DayOfWeek.Thursday, 23, 59, 0); + let utc = new DateTime.UTC(1972, Month.January, 7, DayOfWeek.Friday, 0, 43, 30); + + assertDate(local, utc, TimeZone(-0,44,30), { + String: "Thu Jan 06 1972 23:59:00 GMT-0044 (Greenwich Mean Time)", + UTCString: "Fri, 07 Jan 1972 00:43:30 GMT", + }); +} + +{ + let local = new DateTime.Local(1972, Month.January, 7, DayOfWeek.Friday, 0, 0, 0); + let utc = new DateTime.UTC(1972, Month.January, 7, DayOfWeek.Friday, 0, 44, 30); + + assertDateValue(local.toDate(), utc.toInstant(), TimeZone(+0).toOffset()); + + assertDateString(local.toDate(), { + String: "Fri Jan 07 1972 00:44:30 GMT+0000 (Greenwich Mean Time)", + UTCString: "Fri, 07 Jan 1972 00:44:30 GMT", + }); +} + +{ + let local = new DateTime.Local(1972, Month.January, 7, DayOfWeek.Friday, 0, 44, 30); + let utc = new DateTime.UTC(1972, Month.January, 7, DayOfWeek.Friday, 0, 44, 30); + + assertDate(local, utc, TimeZone(+0), { + String: "Fri Jan 07 1972 00:44:30 GMT+0000 (Greenwich Mean Time)", + UTCString: "Fri, 07 Jan 1972 00:44:30 GMT", + }); +} + +{ + let local = new DateTime.Local(1972, Month.January, 7, DayOfWeek.Friday, 0, 45, 0); + let utc = new DateTime.UTC(1972, Month.January, 7, DayOfWeek.Friday, 0, 45, 0); + + assertDate(local, utc, TimeZone(+0), { + String: "Fri Jan 07 1972 00:45:00 GMT+0000 (Greenwich Mean Time)", + UTCString: "Fri, 07 Jan 1972 00:45:00 GMT", + }); +} + +{ + let local = new DateTime.Local(1972, Month.January, 8, DayOfWeek.Saturday, 0, 0, 0); + let utc = new DateTime.UTC(1972, Month.January, 8, DayOfWeek.Saturday, 0, 0, 0); + + assertDate(local, utc, TimeZone(+0), { + String: "Sat Jan 08 1972 00:00:00 GMT+0000 (Greenwich Mean Time)", + UTCString: "Sat, 08 Jan 1972 00:00:00 GMT", + }); +} +}); + + +// File: Date/Africa_Monrovia.js +// Africa/Tripoli switched from +02:00 to +01:00 and back. + +inTimeZone("Africa/Tripoli", () => { +{ + // +02:00 (standard time) + let local = new DateTime.Local(2012, Month.November, 1, DayOfWeek.Thursday, 0, 0, 0); + let utc = new DateTime.UTC(2012, Month.October, 31, DayOfWeek.Wednesday, 22, 0, 0); + + assertDate(local, utc, TimeZone(+2), { + String: "Thu Nov 01 2012 00:00:00 GMT+0200 (Eastern European Standard Time)", + UTCString: "Wed, 31 Oct 2012 22:00:00 GMT", + }); +} + +{ + // +01:00 (standard time) + let local = new DateTime.Local(2012, Month.December, 1, DayOfWeek.Saturday, 0, 0, 0); + let utc = new DateTime.UTC(2012, Month.November, 30, DayOfWeek.Friday, 23, 0, 0); + + assertDate(local, utc, TimeZone(+1), { + String: "Sat Dec 01 2012 00:00:00 GMT+0100 (Eastern European Standard Time)", + UTCString: "Fri, 30 Nov 2012 23:00:00 GMT", + }); +} + +{ + // +01:00 (daylight savings) + let local = new DateTime.Local(2013, Month.October, 1, DayOfWeek.Tuesday, 0, 0, 0); + let utc = new DateTime.UTC(2013, Month.September, 30, DayOfWeek.Monday, 22, 0, 0); + + assertDate(local, utc, TimeZone(+2), { + String: "Tue Oct 01 2013 00:00:00 GMT+0200 (Eastern European Summer Time)", + UTCString: "Mon, 30 Sep 2013 22:00:00 GMT", + }); +} + +{ + // +02:00 (standard time) + let local = new DateTime.Local(2013, Month.November, 1, DayOfWeek.Friday, 0, 0, 0); + let utc = new DateTime.UTC(2013, Month.October, 31, DayOfWeek.Thursday, 22, 0, 0); + + assertDate(local, utc, TimeZone(+2), { + String: "Fri Nov 01 2013 00:00:00 GMT+0200 (Eastern European Standard Time)", + UTCString: "Thu, 31 Oct 2013 22:00:00 GMT", + }); +} +}); + + +// File: Date/America_Caracas.js +// America/Caracas switched from -04:00 to -04:30 on 2007 Dec 9. + +inTimeZone("America/Caracas", () => { +{ + // -04:00 (standard time) + let local = new DateTime.Local(2007, Month.December, 5, DayOfWeek.Wednesday, 0, 0, 0); + let utc = new DateTime.UTC(2007, Month.December, 5, DayOfWeek.Wednesday, 4, 0, 0); + + assertDate(local, utc, TimeZone(-4), { + String: "Wed Dec 05 2007 00:00:00 GMT-0400 (Venezuela Time)", + DateString: "Wed Dec 05 2007", + TimeString: "00:00:00 GMT-0400 (Venezuela Time)", + UTCString: "Wed, 05 Dec 2007 04:00:00 GMT", + ISOString: "2007-12-05T04:00:00.000Z", + LocaleString: "Wed, 12/05/2007, 12:00:00 AM GMT-4", + LocaleDateString: "Wed, 12/05/2007", + LocaleTimeString: "12:00:00 AM GMT-4", + }); +} + +{ + // -04:30 (standard time) + let local = new DateTime.Local(2007, Month.December, 12, DayOfWeek.Wednesday, 0, 0, 0); + let utc = new DateTime.UTC(2007, Month.December, 12, DayOfWeek.Wednesday, 4, 30, 0); + + assertDate(local, utc, TimeZone(-4, 30), { + String: "Wed Dec 12 2007 00:00:00 GMT-0430 (Venezuela Time)", + DateString: "Wed Dec 12 2007", + TimeString: "00:00:00 GMT-0430 (Venezuela Time)", + UTCString: "Wed, 12 Dec 2007 04:30:00 GMT", + ISOString: "2007-12-12T04:30:00.000Z", + LocaleString: "Wed, 12/12/2007, 12:00:00 AM GMT-4:30", + LocaleDateString: "Wed, 12/12/2007", + LocaleTimeString: "12:00:00 AM GMT-4:30", + }); +} +}); + + +// File: Date/Australia_Lord_Howe.js +// Australia/Lord_Howe time zone offset is +10:30 and daylight savings amount is 00:30. + +inTimeZone("Australia/Lord_Howe", () => { +{ + // +10:30 (standard time) + let local = new DateTime.Local(2010, Month.August, 1, DayOfWeek.Sunday, 0, 0, 0); + let utc = new DateTime.UTC(2010, Month.July, 31, DayOfWeek.Saturday, 13, 30, 0); + + assertDate(local, utc, TimeZone(+10,30), { + String: "Sun Aug 01 2010 00:00:00 GMT+1030 (Lord Howe Standard Time)", + DateString: "Sun Aug 01 2010", + TimeString: "00:00:00 GMT+1030 (Lord Howe Standard Time)", + UTCString: "Sat, 31 Jul 2010 13:30:00 GMT", + ISOString: "2010-07-31T13:30:00.000Z", + LocaleString: "Sun, 08/01/2010, 12:00:00 AM GMT+10:30", + LocaleDateString: "Sun, 08/01/2010", + LocaleTimeString: "12:00:00 AM GMT+10:30", + }); +} + +{ + // +10:30 (daylight savings) + let local = new DateTime.Local(2010, Month.January, 3, DayOfWeek.Sunday, 0, 0, 0); + let utc = new DateTime.UTC(2010, Month.January, 2, DayOfWeek.Saturday, 13, 0, 0); + + assertDate(local, utc, TimeZone(+11), { + String: "Sun Jan 03 2010 00:00:00 GMT+1100 (Lord Howe Daylight Time)", + DateString: "Sun Jan 03 2010", + TimeString: "00:00:00 GMT+1100 (Lord Howe Daylight Time)", + UTCString: "Sat, 02 Jan 2010 13:00:00 GMT", + ISOString: "2010-01-02T13:00:00.000Z", + LocaleString: "Sun, 01/03/2010, 12:00:00 AM GMT+11", + LocaleDateString: "Sun, 01/03/2010", + LocaleTimeString: "12:00:00 AM GMT+11", + }); +} +}); + + +// File: Date/Europe_Amsterdam.js +// Europe/Amsterdam as an example for mean time like timezones after LMT (AMT, NST). +// +// tzdata2022b changed Europe/Amsterdam into a link to Europe/Brussels. + +inTimeZone("Europe/Amsterdam", () => { +{ + let local = new DateTime.Local(1935, Month.January, 1, DayOfWeek.Tuesday, 0, 0, 0); + let utc = new DateTime.UTC(1935, Month.January, 1, DayOfWeek.Tuesday, 0, 0, 0); + + assertDate(local, utc, TimeZone(+0,0,0), { + String: "Tue Jan 01 1935 00:00:00 GMT+0000 (Central European Standard Time)", + UTCString: "Tue, 01 Jan 1935 00:00:00 GMT", + }); +} + +{ + let local = new DateTime.Local(1935, Month.July, 1, DayOfWeek.Monday, 0, 0, 0); + let utc = new DateTime.UTC(1935, Month.June, 30, DayOfWeek.Sunday, 23, 0, 0); + + assertDate(local, utc, TimeZone(+1,0,0), { + String: "Mon Jul 01 1935 00:00:00 GMT+0100 (Central European Summer Time)", + UTCString: "Sun, 30 Jun 1935 23:00:00 GMT", + }); +} +}); + +// Use America/St_Johns as a replacement for the Europe/Amsterdam test case. +// +// Zone America/St_Johns as an example for mean time like timezones after LMT (NST, NDT). + +inTimeZone("America/St_Johns", () => { +{ + let local = new DateTime.Local(1917, Month.January, 1, DayOfWeek.Monday, 0, 0, 0); + let utc = new DateTime.UTC(1917, Month.January, 1, DayOfWeek.Monday, 3, 30, 52); + + assertDate(local, utc, TimeZone(-3,30,52), { + String: "Mon Jan 01 1917 00:00:00 GMT-0330 (Newfoundland Standard Time)", + UTCString: "Mon, 01 Jan 1917 03:30:52 GMT", + }); +} + +{ + let local = new DateTime.Local(1917, Month.July, 1, DayOfWeek.Sunday, 0, 0, 0); + let utc = new DateTime.UTC(1917, Month.July, 1, DayOfWeek.Sunday, 2, 30, 52); + + assertDate(local, utc, TimeZone(-2,30,52), { + String: "Sun Jul 01 1917 00:00:00 GMT-0230 (Newfoundland Daylight Time)", + UTCString: "Sun, 01 Jul 1917 02:30:52 GMT", + }); +} +}); + + +// File: Date/Europe_London.js + +inTimeZone("Europe/London", () => { +{ + // +01:00 (standard time) + let local = new DateTime.Local(1970, Month.January, 1, DayOfWeek.Thursday, 0, 0, 0); + let utc = new DateTime.UTC(1969, Month.December, 31, DayOfWeek.Wednesday, 23, 0, 0); + + assertDate(local, utc, TimeZone(+1), { + String: "Thu Jan 01 1970 00:00:00 GMT+0100 (Greenwich Mean Time)", + DateString: "Thu Jan 01 1970", + TimeString: "00:00:00 GMT+0100 (Greenwich Mean Time)", + UTCString: "Wed, 31 Dec 1969 23:00:00 GMT", + ISOString: "1969-12-31T23:00:00.000Z", + LocaleString: "Thu, 01/01/1970, 12:00:00 AM GMT+1", + LocaleDateString: "Thu, 01/01/1970", + LocaleTimeString: "12:00:00 AM GMT+1", + }); +} +}); + + +// File: Date/Europe_Moscow.js + +inTimeZone("Europe/Moscow", () => { +{ + let local = new DateTime.Local(1970, Month.January, 1, DayOfWeek.Thursday, 0, 0, 0); + let utc = new DateTime.UTC(1969, Month.December, 31, DayOfWeek.Wednesday, 21, 0, 0); + + assertDate(local, utc, TimeZone(+3), { + String: "Thu Jan 01 1970 00:00:00 GMT+0300 (Moscow Standard Time)", + DateString: "Thu Jan 01 1970", + TimeString: "00:00:00 GMT+0300 (Moscow Standard Time)", + UTCString: "Wed, 31 Dec 1969 21:00:00 GMT", + ISOString: "1969-12-31T21:00:00.000Z", + LocaleString: "Thu, 01/01/1970, 12:00:00 AM GMT+3", + LocaleDateString: "Thu, 01/01/1970", + LocaleTimeString: "12:00:00 AM GMT+3", + }); +} + +// Russia was in +02:00 starting on 1991-03-31 until 1992-01-19, +// while still observing DST (transitions 1991-03-31 and 1991-09-29). + +{ + // +03:00 (daylight savings) + let local = new DateTime.Local(1990, Month.September, 1, DayOfWeek.Saturday, 0, 0, 0); + let utc = new DateTime.UTC(1990, Month.August, 31, DayOfWeek.Friday, 20, 0, 0); + + assertDate(local, utc, TimeZone(+4), { + String: "Sat Sep 01 1990 00:00:00 GMT+0400 (Moscow Summer Time)", + DateString: "Sat Sep 01 1990", + TimeString: "00:00:00 GMT+0400 (Moscow Summer Time)", + UTCString: "Fri, 31 Aug 1990 20:00:00 GMT", + ISOString: "1990-08-31T20:00:00.000Z", + LocaleString: "Sat, 09/01/1990, 12:00:00 AM GMT+4", + LocaleDateString: "Sat, 09/01/1990", + LocaleTimeString: "12:00:00 AM GMT+4", + }); +} + +{ + // +03:00 (standard time) + let local = new DateTime.Local(1991, Month.March, 25, DayOfWeek.Monday, 0, 0, 0); + let utc = new DateTime.UTC(1991, Month.March, 24, DayOfWeek.Sunday, 21, 0, 0); + + assertDate(local, utc, TimeZone(+3), { + String: "Mon Mar 25 1991 00:00:00 GMT+0300 (Moscow Standard Time)", + DateString: "Mon Mar 25 1991", + TimeString: "00:00:00 GMT+0300 (Moscow Standard Time)", + UTCString: "Sun, 24 Mar 1991 21:00:00 GMT", + ISOString: "1991-03-24T21:00:00.000Z", + LocaleString: "Mon, 03/25/1991, 12:00:00 AM GMT+3", + LocaleDateString: "Mon, 03/25/1991", + LocaleTimeString: "12:00:00 AM GMT+3", + }); +} + +{ + // +02:00 (daylight savings) + let local = new DateTime.Local(1991, Month.March, 31, DayOfWeek.Sunday, 12, 0, 0); + let utc = new DateTime.UTC(1991, Month.March, 31, DayOfWeek.Sunday, 9, 0, 0); + + assertDate(local, utc, TimeZone(+3), { + String: "Sun Mar 31 1991 12:00:00 GMT+0300 (Moscow Summer Time)", + DateString: "Sun Mar 31 1991", + TimeString: "12:00:00 GMT+0300 (Moscow Summer Time)", + UTCString: "Sun, 31 Mar 1991 09:00:00 GMT", + ISOString: "1991-03-31T09:00:00.000Z", + LocaleString: "Sun, 03/31/1991, 12:00:00 PM GMT+3", + LocaleDateString: "Sun, 03/31/1991", + LocaleTimeString: "12:00:00 PM GMT+3", + }); +} + +{ + // +02:00 (daylight savings) + let local = new DateTime.Local(1991, Month.September, 28, DayOfWeek.Saturday, 0, 0, 0); + let utc = new DateTime.UTC(1991, Month.September, 27, DayOfWeek.Friday, 21, 0, 0); + + assertDate(local, utc, TimeZone(+3), { + String: "Sat Sep 28 1991 00:00:00 GMT+0300 (Moscow Summer Time)", + DateString: "Sat Sep 28 1991", + TimeString: "00:00:00 GMT+0300 (Moscow Summer Time)", + UTCString: "Fri, 27 Sep 1991 21:00:00 GMT", + ISOString: "1991-09-27T21:00:00.000Z", + LocaleString: "Sat, 09/28/1991, 12:00:00 AM GMT+3", + LocaleDateString: "Sat, 09/28/1991", + LocaleTimeString: "12:00:00 AM GMT+3", + }); +} + +{ + // +02:00 (standard time) + let local = new DateTime.Local(1991, Month.September, 30, DayOfWeek.Monday, 0, 0, 0); + let utc = new DateTime.UTC(1991, Month.September, 29, DayOfWeek.Sunday, 22, 0, 0); + + assertDate(local, utc, TimeZone(+2), { + String: "Mon Sep 30 1991 00:00:00 GMT+0200 (Moscow Standard Time)", + DateString: "Mon Sep 30 1991", + TimeString: "00:00:00 GMT+0200 (Moscow Standard Time)", + UTCString: "Sun, 29 Sep 1991 22:00:00 GMT", + ISOString: "1991-09-29T22:00:00.000Z", + LocaleString: "Mon, 09/30/1991, 12:00:00 AM GMT+2", + LocaleDateString: "Mon, 09/30/1991", + LocaleTimeString: "12:00:00 AM GMT+2", + }); +} + +// Russia stopped observing DST in Oct. 2010 (last transition on 2010-10-31), +// and changed timezone from +03:00 to +04:00 on 2011-03-27. + +{ + // +03:00 (daylight savings) + let local = new DateTime.Local(2010, Month.October, 30, DayOfWeek.Saturday, 0, 0, 0); + let utc = new DateTime.UTC(2010, Month.October, 29, DayOfWeek.Friday, 20, 0, 0); + + assertDate(local, utc, TimeZone(+4), { + String: "Sat Oct 30 2010 00:00:00 GMT+0400 (Moscow Summer Time)", + DateString: "Sat Oct 30 2010", + TimeString: "00:00:00 GMT+0400 (Moscow Summer Time)", + UTCString: "Fri, 29 Oct 2010 20:00:00 GMT", + ISOString: "2010-10-29T20:00:00.000Z", + LocaleString: "Sat, 10/30/2010, 12:00:00 AM GMT+4", + LocaleDateString: "Sat, 10/30/2010", + LocaleTimeString: "12:00:00 AM GMT+4", + }); +} + +{ + // +03:00 (standard time) + let local = new DateTime.Local(2010, Month.November, 1, DayOfWeek.Monday, 0, 0, 0); + let utc = new DateTime.UTC(2010, Month.October, 31, DayOfWeek.Sunday, 21, 0, 0); + + assertDate(local, utc, TimeZone(+3), { + String: "Mon Nov 01 2010 00:00:00 GMT+0300 (Moscow Standard Time)", + DateString: "Mon Nov 01 2010", + TimeString: "00:00:00 GMT+0300 (Moscow Standard Time)", + UTCString: "Sun, 31 Oct 2010 21:00:00 GMT", + ISOString: "2010-10-31T21:00:00.000Z", + LocaleString: "Mon, 11/01/2010, 12:00:00 AM GMT+3", + LocaleDateString: "Mon, 11/01/2010", + LocaleTimeString: "12:00:00 AM GMT+3", + }); +} + +{ + // +04:00 (standard time) + let local = new DateTime.Local(2011, Month.October, 30, DayOfWeek.Sunday, 0, 0, 0); + let utc = new DateTime.UTC(2011, Month.October, 29, DayOfWeek.Saturday, 20, 0, 0); + + assertDate(local, utc, TimeZone(+4), { + String: "Sun Oct 30 2011 00:00:00 GMT+0400 (Moscow Standard Time)", + DateString: "Sun Oct 30 2011", + TimeString: "00:00:00 GMT+0400 (Moscow Standard Time)", + UTCString: "Sat, 29 Oct 2011 20:00:00 GMT", + ISOString: "2011-10-29T20:00:00.000Z", + LocaleString: "Sun, 10/30/2011, 12:00:00 AM GMT+4", + LocaleDateString: "Sun, 10/30/2011", + LocaleTimeString: "12:00:00 AM GMT+4", + }); +} + +{ + // +04:00 (standard time) + let local = new DateTime.Local(2011, Month.November, 1, DayOfWeek.Tuesday, 0, 0, 0); + let utc = new DateTime.UTC(2011, Month.October, 31, DayOfWeek.Monday, 20, 0, 0); + + assertDate(local, utc, TimeZone(+4), { + String: "Tue Nov 01 2011 00:00:00 GMT+0400 (Moscow Standard Time)", + DateString: "Tue Nov 01 2011", + TimeString: "00:00:00 GMT+0400 (Moscow Standard Time)", + UTCString: "Mon, 31 Oct 2011 20:00:00 GMT", + ISOString: "2011-10-31T20:00:00.000Z", + LocaleString: "Tue, 11/01/2011, 12:00:00 AM GMT+4", + LocaleDateString: "Tue, 11/01/2011", + LocaleTimeString: "12:00:00 AM GMT+4", + }); +} + +// Russia changed timezone from +04:00 to +03:00 on 2014-10-26. + +{ + // +04:00 (standard time) + let local = new DateTime.Local(2014, Month.October, 26, DayOfWeek.Sunday, 0, 0, 0); + let utc = new DateTime.UTC(2014, Month.October, 25, DayOfWeek.Saturday, 20, 0, 0); + + assertDate(local, utc, TimeZone(+4), { + String: "Sun Oct 26 2014 00:00:00 GMT+0400 (Moscow Standard Time)", + DateString: "Sun Oct 26 2014", + TimeString: "00:00:00 GMT+0400 (Moscow Standard Time)", + UTCString: "Sat, 25 Oct 2014 20:00:00 GMT", + ISOString: "2014-10-25T20:00:00.000Z", + LocaleString: "Sun, 10/26/2014, 12:00:00 AM GMT+4", + LocaleDateString: "Sun, 10/26/2014", + LocaleTimeString: "12:00:00 AM GMT+4", + }); +} + +{ + // +03:00 (standard time) + let local = new DateTime.Local(2014, Month.October, 27, DayOfWeek.Monday, 0, 0, 0); + let utc = new DateTime.UTC(2014, Month.October, 26, DayOfWeek.Sunday, 21, 0, 0); + + assertDate(local, utc, TimeZone(+3), { + String: "Mon Oct 27 2014 00:00:00 GMT+0300 (Moscow Standard Time)", + DateString: "Mon Oct 27 2014", + TimeString: "00:00:00 GMT+0300 (Moscow Standard Time)", + UTCString: "Sun, 26 Oct 2014 21:00:00 GMT", + ISOString: "2014-10-26T21:00:00.000Z", + LocaleString: "Mon, 10/27/2014, 12:00:00 AM GMT+3", + LocaleDateString: "Mon, 10/27/2014", + LocaleTimeString: "12:00:00 AM GMT+3", + }); +} +}); + + +// File: Date/Pacific_Apia.js +// Pacific/Apia switched from -11:00 to +13:00 on 2011 Dec 29 24:00. + +inTimeZone("Pacific/Apia", () => { +{ + // -11:00 (daylight savings) + let local = new DateTime.Local(2011, Month.December, 29, DayOfWeek.Thursday, 0, 0, 0); + let utc = new DateTime.UTC(2011, Month.December, 29, DayOfWeek.Thursday, 10, 0, 0); + + assertDate(local, utc, TimeZone(-10), { + String: "Thu Dec 29 2011 00:00:00 GMT-1000 (Apia Daylight Time)", + DateString: "Thu Dec 29 2011", + TimeString: "00:00:00 GMT-1000 (Apia Daylight Time)", + UTCString: "Thu, 29 Dec 2011 10:00:00 GMT", + ISOString: "2011-12-29T10:00:00.000Z", + LocaleString: "Thu, 12/29/2011, 12:00:00 AM GMT-10", + LocaleDateString: "Thu, 12/29/2011", + LocaleTimeString: "12:00:00 AM GMT-10", + }); +} + +{ + // +13:00 (daylight savings) + let local = new DateTime.Local(2011, Month.December, 31, DayOfWeek.Saturday, 0, 0, 0); + let utc = new DateTime.UTC(2011, Month.December, 30, DayOfWeek.Friday, 10, 0, 0); + + assertDate(local, utc, TimeZone(+14), { + String: "Sat Dec 31 2011 00:00:00 GMT+1400 (Apia Daylight Time)", + DateString: "Sat Dec 31 2011", + TimeString: "00:00:00 GMT+1400 (Apia Daylight Time)", + UTCString: "Fri, 30 Dec 2011 10:00:00 GMT", + ISOString: "2011-12-30T10:00:00.000Z", + LocaleString: "Sat, 12/31/2011, 12:00:00 AM GMT+14", + LocaleDateString: "Sat, 12/31/2011", + LocaleTimeString: "12:00:00 AM GMT+14", + }); +} + +{ + // +13:00 (standard time) + let local = new DateTime.Local(2012, Month.April, 2, DayOfWeek.Monday, 0, 0, 0); + let utc = new DateTime.UTC(2012, Month.April, 1, DayOfWeek.Sunday, 11, 0, 0); + + assertDate(local, utc, TimeZone(+13), { + String: "Mon Apr 02 2012 00:00:00 GMT+1300 (Apia Standard Time)", + DateString: "Mon Apr 02 2012", + TimeString: "00:00:00 GMT+1300 (Apia Standard Time)", + UTCString: "Sun, 01 Apr 2012 11:00:00 GMT", + ISOString: "2012-04-01T11:00:00.000Z", + LocaleString: "Mon, 04/02/2012, 12:00:00 AM GMT+13", + LocaleDateString: "Mon, 04/02/2012", + LocaleTimeString: "12:00:00 AM GMT+13", + }); +} +}); + + +// File: Date/Pacific_Chatham.js +// Pacific/Chatham time zone offset is 12:45. + +inTimeZone("Pacific/Chatham", () => { +{ + // +12:45 (standard time) + let local = new DateTime.Local(2010, Month.August, 1, DayOfWeek.Sunday, 0, 0, 0); + let utc = new DateTime.UTC(2010, Month.July, 31, DayOfWeek.Saturday, 11, 15, 0); + + assertDate(local, utc, TimeZone(+12,45), { + String: "Sun Aug 01 2010 00:00:00 GMT+1245 (Chatham Standard Time)", + DateString: "Sun Aug 01 2010", + TimeString: "00:00:00 GMT+1245 (Chatham Standard Time)", + UTCString: "Sat, 31 Jul 2010 11:15:00 GMT", + ISOString: "2010-07-31T11:15:00.000Z", + LocaleString: "Sun, 08/01/2010, 12:00:00 AM GMT+12:45", + LocaleDateString: "Sun, 08/01/2010", + LocaleTimeString: "12:00:00 AM GMT+12:45", + }); +} + +{ + // +12:45 (daylight savings) + let local = new DateTime.Local(2010, Month.January, 3, DayOfWeek.Sunday, 0, 0, 0); + let utc = new DateTime.UTC(2010, Month.January, 2, DayOfWeek.Saturday, 10, 15, 0); + + assertDate(local, utc, TimeZone(+13,45), { + String: "Sun Jan 03 2010 00:00:00 GMT+1345 (Chatham Daylight Time)", + DateString: "Sun Jan 03 2010", + TimeString: "00:00:00 GMT+1345 (Chatham Daylight Time)", + UTCString: "Sat, 02 Jan 2010 10:15:00 GMT", + ISOString: "2010-01-02T10:15:00.000Z", + LocaleString: "Sun, 01/03/2010, 12:00:00 AM GMT+13:45", + LocaleDateString: "Sun, 01/03/2010", + LocaleTimeString: "12:00:00 AM GMT+13:45", + }); +} +}); + + +// File: Date/Pacific_Kiritimati.js +// Pacific/Kiritimati time zone offset is +14:00. + +inTimeZone("Pacific/Kiritimati", () => { +{ + // +14:00 (standard time) + let local = new DateTime.Local(2010, Month.August, 1, DayOfWeek.Sunday, 0, 0, 0); + let utc = new DateTime.UTC(2010, Month.July, 31, DayOfWeek.Saturday, 10, 0, 0); + + assertDate(local, utc, TimeZone(+14), { + String: "Sun Aug 01 2010 00:00:00 GMT+1400 (Line Islands Time)", + DateString: "Sun Aug 01 2010", + TimeString: "00:00:00 GMT+1400 (Line Islands Time)", + UTCString: "Sat, 31 Jul 2010 10:00:00 GMT", + ISOString: "2010-07-31T10:00:00.000Z", + LocaleString: "Sun, 08/01/2010, 12:00:00 AM GMT+14", + LocaleDateString: "Sun, 08/01/2010", + LocaleTimeString: "12:00:00 AM GMT+14", + }); +} + +// Pacific/Kiritimati time zone offset was -10:40 until Oct. 1979. + +{ + // -10:40 (standard time) + let local = new DateTime.Local(1975, Month.January, 1, DayOfWeek.Wednesday, 0, 0, 0); + let utc = new DateTime.UTC(1975, Month.January, 1, DayOfWeek.Wednesday, 10, 40, 0); + + assertDate(local, utc, TimeZone(-10,40), { + String: "Wed Jan 01 1975 00:00:00 GMT-1040 (Line Islands Time)", + DateString: "Wed Jan 01 1975", + TimeString: "00:00:00 GMT-1040 (Line Islands Time)", + UTCString: "Wed, 01 Jan 1975 10:40:00 GMT", + ISOString: "1975-01-01T10:40:00.000Z", + LocaleString: "Wed, 01/01/1975, 12:00:00 AM GMT-10:40", + LocaleDateString: "Wed, 01/01/1975", + LocaleTimeString: "12:00:00 AM GMT-10:40", + }); +} +}); + + +// File: Date/Pacifi_Niue.js +// Pacific/Niue time zone offset was -11:20 from 1952 through 1964. + +inTimeZone("Pacific/Niue", () => { +{ + // -11:20 (standard time) + let local = new DateTime.Local(1956, Month.January, 1, DayOfWeek.Sunday, 0, 0, 0); + let utc = new DateTime.UTC(1956, Month.January, 1, DayOfWeek.Sunday, 11, 20, 0); + + assertDate(local, utc, TimeZone(-11,20), { + String: "Sun Jan 01 1956 00:00:00 GMT-1120 (Niue Time)", + DateString: "Sun Jan 01 1956", + TimeString: "00:00:00 GMT-1120 (Niue Time)", + UTCString: "Sun, 01 Jan 1956 11:20:00 GMT", + ISOString: "1956-01-01T11:20:00.000Z", + LocaleString: "Sun, 01/01/1956, 12:00:00 AM GMT-11:20", + LocaleDateString: "Sun, 01/01/1956", + LocaleTimeString: "12:00:00 AM GMT-11:20", + }); +} +}); + + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/time-zones-pedantic.js b/js/src/tests/non262/Date/time-zones-pedantic.js new file mode 100644 index 0000000000..c3445ed5fd --- /dev/null +++ b/js/src/tests/non262/Date/time-zones-pedantic.js @@ -0,0 +1,15 @@ +// |reftest| skip-if(xulRuntime.OS=="WINNT"||xulRuntime.OS=="Darwin") -- Skip on OS X in addition to Windows + +// Contains the tests from "time-zones.js" which fail on OS X. + +// bug 637244 +inTimeZone("Asia/Novosibirsk", () => { + let dt1 = new Date(1984, Month.April, 1, -1); + assertDateTime(dt1, "Sat Mar 31 1984 23:00:00 GMT+0700 (NOVT)", "+07", "Novosibirsk Standard Time"); + + let dt2 = new Date(1984, Month.April, 1); + assertDateTime(dt2, "Sun Apr 01 1984 01:00:00 GMT+0800 (NOVST)", "+08", "Novosibirsk Summer Time"); +}); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/time-zones-posix.js b/js/src/tests/non262/Date/time-zones-posix.js new file mode 100644 index 0000000000..c2d7cc20c9 --- /dev/null +++ b/js/src/tests/non262/Date/time-zones-posix.js @@ -0,0 +1,160 @@ +// |reftest| skip-if(xulRuntime.OS=="WINNT"&&!xulRuntime.shell) -- Windows browser in automation doesn't pick up new time zones correctly + +// Repeats the test from "time-zones.js", but uses POSIX instead of IANA names +// for the time zones. This allows to run these tests on Windows, too. + +// From bug 1330149: +// +// Windows only supports a very limited set of IANA time zone names for the TZ +// environment variable. +// +// TZ format supported by Windows: "TZ=tzn[+|-]hh[:mm[:ss]][dzn]". +// +// Complete list of all IANA time zone ids matching that format. +// +// From tzdata's "northamerica" file: +// EST5EDT +// CST6CDT +// MST7MDT +// PST8PDT +// +// From tzdata's "backward" file: +// GMT+0 +// GMT-0 +// GMT0 +// +// Also supported on Windows even though they don't match the format listed +// above. +// +// From tzdata's "backward" file: +// UCT +// UTC +// +// From tzdata's "etcetera" file: +// GMT + + +// Perform the following replacements: +// America/New_York -> EST5EDT +// America/Chicago -> CST6CDT +// America/Denver -> MST7MDT +// America/Los_Angeles -> PST8PDT +// +// And remove any tests not matching one of the four time zones from above. + +// bug 294908 +inTimeZone("EST5EDT", () => { + let dt = new Date(2003, Month.April, 6, 2, 30, 00); + assertDateTime(dt, "Sun Apr 06 2003 03:30:00 GMT-0400 (EDT)", "Eastern Daylight Time"); +}); + +// bug 610183 +inTimeZone("PST8PDT", () => { + let dt = new Date(2014, Month.November, 2, 1, 47, 42); + assertDateTime(dt, "Sun Nov 02 2014 01:47:42 GMT-0700 (PDT)", "Pacific Daylight Time"); +}); + +// bug 629465 +inTimeZone("MST7MDT", () => { + let dt1 = new Date(Date.UTC(2015, Month.November, 1, 0, 0, 0) + 6 * msPerHour); + assertDateTime(dt1, "Sun Nov 01 2015 00:00:00 GMT-0600 (MDT)", "Mountain Daylight Time"); + + let dt2 = new Date(Date.UTC(2015, Month.November, 1, 1, 0, 0) + 6 * msPerHour); + assertDateTime(dt2, "Sun Nov 01 2015 01:00:00 GMT-0600 (MDT)", "Mountain Daylight Time"); + + let dt3 = new Date(Date.UTC(2015, Month.November, 1, 1, 0, 0) + 7 * msPerHour); + assertDateTime(dt3, "Sun Nov 01 2015 01:00:00 GMT-0700 (MST)", "Mountain Standard Time"); +}); + +// bug 742427 +inTimeZone("EST5EDT", () => { + let dt = new Date(2009, Month.March, 8, 1, 0, 0); + assertDateTime(dt, "Sun Mar 08 2009 01:00:00 GMT-0500 (EST)", "Eastern Standard Time"); + dt.setHours(dt.getHours() + 1); + assertDateTime(dt, "Sun Mar 08 2009 03:00:00 GMT-0400 (EDT)", "Eastern Daylight Time"); +}); +inTimeZone("MST7MDT", () => { + let dt = new Date(2009, Month.March, 8, 1, 0, 0); + assertDateTime(dt, "Sun Mar 08 2009 01:00:00 GMT-0700 (MST)", "Mountain Standard Time"); + dt.setHours(dt.getHours() + 1); + assertDateTime(dt, "Sun Mar 08 2009 03:00:00 GMT-0600 (MDT)", "Mountain Daylight Time"); +}); +inTimeZone("EST5EDT", () => { + let dt1 = new Date(Date.UTC(2008, Month.March, 9, 0, 0, 0) + 5 * msPerHour); + assertDateTime(dt1, "Sun Mar 09 2008 00:00:00 GMT-0500 (EST)", "Eastern Standard Time"); + + let dt2 = new Date(Date.UTC(2008, Month.March, 9, 1, 0, 0) + 5 * msPerHour); + assertDateTime(dt2, "Sun Mar 09 2008 01:00:00 GMT-0500 (EST)", "Eastern Standard Time"); + + let dt3 = new Date(Date.UTC(2008, Month.March, 9, 4, 0, 0) + 4 * msPerHour); + assertDateTime(dt3, "Sun Mar 09 2008 04:00:00 GMT-0400 (EDT)", "Eastern Daylight Time"); +}); + +// bug 802627 +inTimeZone("EST5EDT", () => { + let dt = new Date(0); + assertDateTime(dt, "Wed Dec 31 1969 19:00:00 GMT-0500 (EST)", "Eastern Standard Time"); +}); + +// bug 879261 +inTimeZone("EST5EDT", () => { + let dt1 = new Date(1362891600000); + assertDateTime(dt1, "Sun Mar 10 2013 00:00:00 GMT-0500 (EST)", "Eastern Standard Time"); + + let dt2 = new Date(dt1.setHours(dt1.getHours() + 24)); + assertDateTime(dt2, "Mon Mar 11 2013 00:00:00 GMT-0400 (EDT)", "Eastern Daylight Time"); +}); +inTimeZone("PST8PDT", () => { + let dt1 = new Date(2014, Month.January, 1); + assertDateTime(dt1, "Wed Jan 01 2014 00:00:00 GMT-0800 (PST)", "Pacific Standard Time"); + + let dt2 = new Date(2014, Month.August, 1); + assertDateTime(dt2, "Fri Aug 01 2014 00:00:00 GMT-0700 (PDT)", "Pacific Daylight Time"); +}); +inTimeZone("EST5EDT", () => { + let dt1 = new Date(2016, Month.October, 14, 3, 5, 9); + assertDateTime(dt1, "Fri Oct 14 2016 03:05:09 GMT-0400 (EDT)", "Eastern Daylight Time"); + + let dt2 = new Date(2016, Month.January, 9, 23, 26, 40); + assertDateTime(dt2, "Sat Jan 09 2016 23:26:40 GMT-0500 (EST)", "Eastern Standard Time"); +}); + +// bug 1084547 +inTimeZone("EST5EDT", () => { + let dt = new Date(Date.parse("2014-11-02T02:00:00-04:00")); + assertDateTime(dt, "Sun Nov 02 2014 01:00:00 GMT-0500 (EST)", "Eastern Standard Time"); + + dt.setMilliseconds(0); + assertDateTime(dt, "Sun Nov 02 2014 01:00:00 GMT-0400 (EDT)", "Eastern Daylight Time"); +}); + +// bug 1303306 +inTimeZone("EST5EDT", () => { + let dt = new Date(2016, Month.September, 15, 16, 14, 48); + assertDateTime(dt, "Thu Sep 15 2016 16:14:48 GMT-0400 (EDT)", "Eastern Daylight Time"); +}); + +// bug 1317364 +inTimeZone("PST8PDT", () => { + let dt = new Date(2016, Month.March, 13, 2, 30, 0, 0); + assertDateTime(dt, "Sun Mar 13 2016 03:30:00 GMT-0700 (PDT)", "Pacific Daylight Time"); + + let dt2 = new Date(2016, Month.January, 5, 0, 30, 30, 500); + assertDateTime(dt2, "Tue Jan 05 2016 00:30:30 GMT-0800 (PST)", "Pacific Standard Time"); + + let dt3 = new Date(dt2.getTime()); + dt3.setMonth(dt2.getMonth() + 2); + dt3.setDate(dt2.getDate() + 7 + 1); + dt3.setHours(dt2.getHours() + 2); + + assertEq(dt3.getHours(), 3); +}); + +// bug 1355272 +inTimeZone("PST8PDT", () => { + let dt = new Date(2017, Month.April, 10, 17, 25, 07); + assertDateTime(dt, "Mon Apr 10 2017 17:25:07 GMT-0700 (PDT)", "Pacific Daylight Time"); +}); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/time-zones.js b/js/src/tests/non262/Date/time-zones.js new file mode 100644 index 0000000000..da2b328be7 --- /dev/null +++ b/js/src/tests/non262/Date/time-zones.js @@ -0,0 +1,261 @@ +// |reftest| skip-if(xulRuntime.OS=="WINNT") -- Windows doesn't accept IANA names for the TZ env variable + +// bug 158328 +inTimeZone("Europe/London", () => { + let dt1 = new Date(2002, Month.July, 19, 16, 10, 55); + assertDateTime(dt1, "Fri Jul 19 2002 16:10:55 GMT+0100 (BST)", "British Summer Time"); + + let dt2 = new Date(2009, Month.December, 24, 13, 44, 52); + assertDateTime(dt2, "Thu Dec 24 2009 13:44:52 GMT+0000 (GMT)", "Greenwich Mean Time"); +}); + +// bug 294908 +inTimeZone("America/New_York", () => { + let dt = new Date(2003, Month.April, 6, 2, 30, 00); + assertDateTime(dt, "Sun Apr 06 2003 03:30:00 GMT-0400 (EDT)", "Eastern Daylight Time"); +}); + +// bug 610183 +inTimeZone("America/Los_Angeles", () => { + let dt = new Date(2014, Month.November, 2, 1, 47, 42); + assertDateTime(dt, "Sun Nov 02 2014 01:47:42 GMT-0700 (PDT)", "Pacific Daylight Time"); +}); + +// bug 629465 +inTimeZone("America/Denver", () => { + let dt1 = new Date(Date.UTC(2015, Month.November, 1, 0, 0, 0) + 6 * msPerHour); + assertDateTime(dt1, "Sun Nov 01 2015 00:00:00 GMT-0600 (MDT)", "Mountain Daylight Time"); + + let dt2 = new Date(Date.UTC(2015, Month.November, 1, 1, 0, 0) + 6 * msPerHour); + assertDateTime(dt2, "Sun Nov 01 2015 01:00:00 GMT-0600 (MDT)", "Mountain Daylight Time"); + + let dt3 = new Date(Date.UTC(2015, Month.November, 1, 1, 0, 0) + 7 * msPerHour); + assertDateTime(dt3, "Sun Nov 01 2015 01:00:00 GMT-0700 (MST)", "Mountain Standard Time"); +}); + +// bug 637244 +inTimeZone("Europe/Helsinki", () => { + let dt1 = new Date(2016, Month.March, 27, 2, 59); + assertDateTime(dt1, "Sun Mar 27 2016 02:59:00 GMT+0200 (EET)", "Eastern European Standard Time"); + + let dt2 = new Date(2016, Month.March, 27, 3, 0); + assertDateTime(dt2, "Sun Mar 27 2016 04:00:00 GMT+0300 (EEST)", "Eastern European Summer Time"); +}); + +// bug 718175 +inTimeZone("Europe/London", () => { + let dt = new Date(0); + assertEq(dt.getHours(), 1); +}); + +// bug 719274 +inTimeZone("Pacific/Auckland", () => { + let dt = new Date(2012, Month.January, 19, 12, 54, 27); + assertDateTime(dt, "Thu Jan 19 2012 12:54:27 GMT+1300 (NZDT)", "New Zealand Daylight Time"); +}); + +// bug 742427 +inTimeZone("Europe/Paris", () => { + let dt1 = new Date(2009, Month.March, 29, 1, 0, 0); + assertDateTime(dt1, "Sun Mar 29 2009 01:00:00 GMT+0100 (CET)", "Central European Standard Time"); + dt1.setHours(dt1.getHours() + 1); + assertDateTime(dt1, "Sun Mar 29 2009 03:00:00 GMT+0200 (CEST)", "Central European Summer Time"); + + let dt2 = new Date(2010, Month.March, 29, 1, 0, 0); + assertDateTime(dt2, "Mon Mar 29 2010 01:00:00 GMT+0200 (CEST)", "Central European Summer Time"); + dt2.setHours(dt2.getHours() + 1); + assertDateTime(dt2, "Mon Mar 29 2010 02:00:00 GMT+0200 (CEST)", "Central European Summer Time"); +}); +inTimeZone("America/New_York", () => { + let dt = new Date(2009, Month.March, 8, 1, 0, 0); + assertDateTime(dt, "Sun Mar 08 2009 01:00:00 GMT-0500 (EST)", "Eastern Standard Time"); + dt.setHours(dt.getHours() + 1); + assertDateTime(dt, "Sun Mar 08 2009 03:00:00 GMT-0400 (EDT)", "Eastern Daylight Time"); +}); +inTimeZone("America/Denver", () => { + let dt = new Date(2009, Month.March, 8, 1, 0, 0); + assertDateTime(dt, "Sun Mar 08 2009 01:00:00 GMT-0700 (MST)", "Mountain Standard Time"); + dt.setHours(dt.getHours() + 1); + assertDateTime(dt, "Sun Mar 08 2009 03:00:00 GMT-0600 (MDT)", "Mountain Daylight Time"); +}); +inTimeZone("America/New_York", () => { + let dt1 = new Date(Date.UTC(2008, Month.March, 9, 0, 0, 0) + 5 * msPerHour); + assertDateTime(dt1, "Sun Mar 09 2008 00:00:00 GMT-0500 (EST)", "Eastern Standard Time"); + + let dt2 = new Date(Date.UTC(2008, Month.March, 9, 1, 0, 0) + 5 * msPerHour); + assertDateTime(dt2, "Sun Mar 09 2008 01:00:00 GMT-0500 (EST)", "Eastern Standard Time"); + + let dt3 = new Date(Date.UTC(2008, Month.March, 9, 4, 0, 0) + 4 * msPerHour); + assertDateTime(dt3, "Sun Mar 09 2008 04:00:00 GMT-0400 (EDT)", "Eastern Daylight Time"); +}); +inTimeZone("Europe/Paris", () => { + let dt1 = new Date(Date.UTC(2008, Month.March, 30, 0, 0, 0) - 1 * msPerHour); + assertDateTime(dt1, "Sun Mar 30 2008 00:00:00 GMT+0100 (CET)", "Central European Standard Time"); + + let dt2 = new Date(Date.UTC(2008, Month.March, 30, 1, 0, 0) - 1 * msPerHour); + assertDateTime(dt2, "Sun Mar 30 2008 01:00:00 GMT+0100 (CET)", "Central European Standard Time"); + + let dt3 = new Date(Date.UTC(2008, Month.March, 30, 3, 0, 0) - 2 * msPerHour); + assertDateTime(dt3, "Sun Mar 30 2008 03:00:00 GMT+0200 (CEST)", "Central European Summer Time"); + + let dt4 = new Date(Date.UTC(2008, Month.March, 30, 4, 0, 0) - 2 * msPerHour); + assertDateTime(dt4, "Sun Mar 30 2008 04:00:00 GMT+0200 (CEST)", "Central European Summer Time"); +}); + +// bug 802627 +inTimeZone("America/New_York", () => { + let dt = new Date(0); + assertDateTime(dt, "Wed Dec 31 1969 19:00:00 GMT-0500 (EST)", "Eastern Standard Time"); +}); + +// bug 819820 +inTimeZone("Europe/London", () => { + let dt1 = new Date(Date.UTC(2012, Month.October, 28, 0, 59, 59)); + assertDateTime(dt1, "Sun Oct 28 2012 01:59:59 GMT+0100 (BST)", "British Summer Time"); + + let dt2 = new Date(Date.UTC(2012, Month.October, 28, 1, 0, 0)); + assertDateTime(dt2, "Sun Oct 28 2012 01:00:00 GMT+0000 (GMT)", "Greenwich Mean Time"); + + let dt3 = new Date(Date.UTC(2012, Month.October, 28, 1, 59, 59)); + assertDateTime(dt3, "Sun Oct 28 2012 01:59:59 GMT+0000 (GMT)", "Greenwich Mean Time"); + + let dt4 = new Date(Date.UTC(2012, Month.October, 28, 2, 0, 0)); + assertDateTime(dt4, "Sun Oct 28 2012 02:00:00 GMT+0000 (GMT)", "Greenwich Mean Time"); +}); + +// bug 879261 +inTimeZone("America/New_York", () => { + let dt1 = new Date(1362891600000); + assertDateTime(dt1, "Sun Mar 10 2013 00:00:00 GMT-0500 (EST)", "Eastern Standard Time"); + + let dt2 = new Date(dt1.setHours(dt1.getHours() + 24)); + assertDateTime(dt2, "Mon Mar 11 2013 00:00:00 GMT-0400 (EDT)", "Eastern Daylight Time"); +}); +inTimeZone("America/Los_Angeles", () => { + let dt1 = new Date(2014, Month.January, 1); + assertDateTime(dt1, "Wed Jan 01 2014 00:00:00 GMT-0800 (PST)", "Pacific Standard Time"); + + let dt2 = new Date(2014, Month.August, 1); + assertDateTime(dt2, "Fri Aug 01 2014 00:00:00 GMT-0700 (PDT)", "Pacific Daylight Time"); +}); +inTimeZone("America/New_York", () => { + let dt1 = new Date(2016, Month.October, 14, 3, 5, 9); + assertDateTime(dt1, "Fri Oct 14 2016 03:05:09 GMT-0400 (EDT)", "Eastern Daylight Time"); + + let dt2 = new Date(2016, Month.January, 9, 23, 26, 40); + assertDateTime(dt2, "Sat Jan 09 2016 23:26:40 GMT-0500 (EST)", "Eastern Standard Time"); +}); + +// bug 994086 +inTimeZone("Europe/Vienna", () => { + let dt1 = new Date(2014, Month.March, 30, 2, 0); + assertDateTime(dt1, "Sun Mar 30 2014 03:00:00 GMT+0200 (CEST)", "Central European Summer Time"); + + let dt2 = new Date(2014, Month.March, 30, 3, 0); + assertDateTime(dt2, "Sun Mar 30 2014 03:00:00 GMT+0200 (CEST)", "Central European Summer Time"); + + let dt3 = new Date(2014, Month.March, 30, 4, 0); + assertDateTime(dt3, "Sun Mar 30 2014 04:00:00 GMT+0200 (CEST)", "Central European Summer Time"); +}); + +// bug 1084434 +inTimeZone("America/Sao_Paulo", () => { + let dt = new Date(2014, Month.October, 19); + assertEq(dt.getDate(), 19); + assertEq(dt.getHours(), 1); + assertDateTime(dt, "Sun Oct 19 2014 01:00:00 GMT-0200 (BRST)", "-02", "Brasilia Summer Time"); +}); + +// bug 1084547 +inTimeZone("America/New_York", () => { + let dt = new Date(Date.parse("2014-11-02T02:00:00-04:00")); + assertDateTime(dt, "Sun Nov 02 2014 01:00:00 GMT-0500 (EST)", "Eastern Standard Time"); + + dt.setMilliseconds(0); + assertDateTime(dt, "Sun Nov 02 2014 01:00:00 GMT-0400 (EDT)", "Eastern Daylight Time"); +}); + +// bug 1118690 +inTimeZone("Europe/London", () => { + let dt = new Date(1965, Month.January, 1); + assertEq(dt.getFullYear(), 1965); +}); + +// bug 1155096 +inTimeZone("Europe/Moscow", () => { + let dt1 = new Date(1981, Month.March, 32); + assertEq(dt1.getDate(), 1); + + let dt2 = new Date(1982, Month.March, 32); + assertEq(dt2.getDate(), 1); + + let dt3 = new Date(1983, Month.March, 32); + assertEq(dt3.getDate(), 1); + + let dt4 = new Date(1984, Month.March, 32); + assertEq(dt4.getDate(), 1); +}); + +// bug 1284507 +inTimeZone("Atlantic/Azores", () => { + let dt1 = new Date(2017, Month.March, 25, 0, 0, 0); + assertDateTime(dt1, "Sat Mar 25 2017 00:00:00 GMT-0100 (AZOT)", "-01", "Azores Standard Time"); + + let dt2 = new Date(2016, Month.October, 30, 0, 0, 0); + assertDateTime(dt2, "Sun Oct 30 2016 00:00:00 GMT+0000 (AZOST)", "+00", "Azores Summer Time"); + + let dt3 = new Date(2016, Month.October, 30, 23, 0, 0); + assertDateTime(dt3, "Sun Oct 30 2016 23:00:00 GMT-0100 (AZOT)", "-01", "Azores Standard Time"); +}); + +// bug 1303306 +inTimeZone("America/New_York", () => { + let dt = new Date(2016, Month.September, 15, 16, 14, 48); + assertDateTime(dt, "Thu Sep 15 2016 16:14:48 GMT-0400 (EDT)", "Eastern Daylight Time"); +}); + +// bug 1317364 +inTimeZone("America/Los_Angeles", () => { + let dt = new Date(2016, Month.March, 13, 2, 30, 0, 0); + assertDateTime(dt, "Sun Mar 13 2016 03:30:00 GMT-0700 (PDT)", "Pacific Daylight Time"); + + let dt2 = new Date(2016, Month.January, 5, 0, 30, 30, 500); + assertDateTime(dt2, "Tue Jan 05 2016 00:30:30 GMT-0800 (PST)", "Pacific Standard Time"); + + let dt3 = new Date(dt2.getTime()); + dt3.setMonth(dt2.getMonth() + 2); + dt3.setDate(dt2.getDate() + 7 + 1); + dt3.setHours(dt2.getHours() + 2); + + assertEq(dt3.getHours(), 3); +}); + +// bug 1335818 +inTimeZone("Asia/Jerusalem", () => { + let dt1 = new Date(2013, Month.March, 22, 1, 0, 0, 0); + assertDateTime(dt1, "Fri Mar 22 2013 01:00:00 GMT+0200 (IST)", "Israel Standard Time"); + + let dt2 = new Date(2013, Month.March, 22, 2, 0, 0, 0); + assertDateTime(dt2, "Fri Mar 22 2013 02:00:00 GMT+0200 (IST)", "Israel Standard Time"); + + let dt3 = new Date(2013, Month.March, 22, 3, 0, 0, 0); + assertDateTime(dt3, "Fri Mar 22 2013 03:00:00 GMT+0200 (IST)", "Israel Standard Time"); + + let dt4 = new Date(2013, Month.March, 29, 1, 0, 0, 0); + assertDateTime(dt4, "Fri Mar 29 2013 01:00:00 GMT+0200 (IST)", "Israel Standard Time"); + + let dt5 = new Date(2013, Month.March, 29, 2, 0, 0, 0); + assertDateTime(dt5, "Fri Mar 29 2013 03:00:00 GMT+0300 (IDT)", "Israel Daylight Time"); + + let dt6 = new Date(2013, Month.March, 29, 3, 0, 0, 0); + assertDateTime(dt6, "Fri Mar 29 2013 03:00:00 GMT+0300 (IDT)", "Israel Daylight Time"); +}); + +// bug 1355272 +inTimeZone("America/Los_Angeles", () => { + let dt = new Date(2017, Month.April, 10, 17, 25, 07); + assertDateTime(dt, "Mon Apr 10 2017 17:25:07 GMT-0700 (PDT)", "Pacific Daylight Time"); +}); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/timeclip.js b/js/src/tests/non262/Date/timeclip.js new file mode 100644 index 0000000000..50bde39e77 --- /dev/null +++ b/js/src/tests/non262/Date/timeclip.js @@ -0,0 +1,42 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommonn.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 747197; +var summary = "TimeClip behavior for very large numbers"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function addToLimit(n) { return 8.64e15 + n; } + +assertEq(8.64e15 === addToLimit(0.0), true); +assertEq(8.64e15 === addToLimit(0.5), true); +assertEq(8.64e15 === addToLimit(0.5000000000000001), false); + +var times = + [Number.MAX_VALUE, + -Number.MAX_VALUE, + Infinity, + -Infinity, + addToLimit(0.5000000000000001), + -addToLimit(0.5000000000000001)]; + +for (var i = 0, len = times.length; i < len; i++) +{ + var d = new Date(); + assertEq(d.setTime(times[i]), NaN, "times[" + i + "]"); + assertEq(d.getTime(), NaN); + assertEq(d.valueOf(), NaN); +} + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Date/to-temporal-instant.js b/js/src/tests/non262/Date/to-temporal-instant.js new file mode 100644 index 0000000000..341a456725 --- /dev/null +++ b/js/src/tests/non262/Date/to-temporal-instant.js @@ -0,0 +1,62 @@ +// |reftest| skip-if(!this.hasOwnProperty("Temporal")) + +const min = new Date(-8640000000000000).toTemporalInstant(); +const max = new Date(8640000000000000).toTemporalInstant(); +const epoch = new Date(0).toTemporalInstant(); + +const minTemporalInstant = new Temporal.Instant(-8640000000000000000000n) +const maxTemporalInstant = new Temporal.Instant(8640000000000000000000n) +const zeroInstant = new Temporal.Instant(0n) + +let zero = Temporal.Duration.from({nanoseconds: 0}); +let one = Temporal.Duration.from({nanoseconds: 1}); +let minusOne = Temporal.Duration.from({nanoseconds: -1}); + +//Test invalid date +{ + const invalidDate = new Date(NaN); + assertThrowsInstanceOf(() => invalidDate.toTemporalInstant(), RangeError); +} + +//Test Temporal.Instant properties +{ + // epochNanoseconds + assertEq(min.epochNanoseconds, minTemporalInstant.epochNanoseconds); + assertEq(max.epochNanoseconds, maxTemporalInstant.epochNanoseconds); + assertEq(epoch.epochNanoseconds, zeroInstant.epochNanoseconds); + + // toZonedDateTime + assertEq(min.toZonedDateTimeISO('UTC').toString(), minTemporalInstant.toZonedDateTimeISO('UTC').toString()); + assertEq(max.toZonedDateTimeISO('UTC').toString(), maxTemporalInstant.toZonedDateTimeISO('UTC').toString()); + assertEq(epoch.toZonedDateTimeISO('UTC').toString(), zeroInstant.toZonedDateTimeISO('UTC').toString()); +} + +// Test values around the minimum/maximum instant. +{ + // Adding zero to the minimum instant. + assertEq(min.add(zero).epochNanoseconds, min.epochNanoseconds); + assertEq(min.subtract(zero).epochNanoseconds, min.epochNanoseconds); + + // Adding zero to the maximum instant. + assertEq(max.add(zero).epochNanoseconds, max.epochNanoseconds); + assertEq(max.subtract(zero).epochNanoseconds, max.epochNanoseconds); + + // Adding one to the minimum instant. + assertEq(min.add(one).epochNanoseconds, min.epochNanoseconds + 1n); + assertEq(min.subtract(minusOne).epochNanoseconds, min.epochNanoseconds + 1n); + + // Subtracting one from the maximum instant. + assertEq(max.add(minusOne).epochNanoseconds, max.epochNanoseconds - 1n); + assertEq(max.subtract(one).epochNanoseconds, max.epochNanoseconds - 1n); + + // Subtracting one from the minimum instant. + assertThrowsInstanceOf(() => min.add(minusOne), RangeError); + assertThrowsInstanceOf(() => min.subtract(one), RangeError); + + // Adding one to the maximum instant. + assertThrowsInstanceOf(() => max.add(one), RangeError); + assertThrowsInstanceOf(() => max.subtract(minusOne), RangeError); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/toISOString-01.js b/js/src/tests/non262/Date/toISOString-01.js new file mode 100644 index 0000000000..cc300a6604 --- /dev/null +++ b/js/src/tests/non262/Date/toISOString-01.js @@ -0,0 +1,53 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 730831; +var summary = 'Date.prototype.toISOString returns an invalid ISO-8601 string'; + +print(BUGNUMBER + ": " + summary); + +function iso(t) { + return new Date(t).toISOString(); +} + +function utc(year, month, day, hour, minute, second, millis) { + var date = new Date(0); + date.setUTCFullYear(year, month - 1, day); + date.setUTCHours(hour, minute, second, millis); + return date.getTime(); +} + + +// Values around maximum date for simple iso format. +var maxDateSimple = utc(9999, 12, 31, 23, 59, 59, 999); +assertEq(iso(maxDateSimple - 1), "9999-12-31T23:59:59.998Z"); +assertEq(iso(maxDateSimple ), "9999-12-31T23:59:59.999Z"); +assertEq(iso(maxDateSimple + 1), "+010000-01-01T00:00:00.000Z"); + + +// Values around minimum date for simple iso format. +var minDateSimple = utc(0, 1, 1, 0, 0, 0, 0); +assertEq(iso(minDateSimple - 1), "-000001-12-31T23:59:59.999Z"); +assertEq(iso(minDateSimple ), "0000-01-01T00:00:00.000Z"); +assertEq(iso(minDateSimple + 1), "0000-01-01T00:00:00.001Z"); + + +// Values around maximum date for extended iso format. +var maxDateExtended = utc(+275760, 9, 13, 0, 0, 0, 0); +assertEq(maxDateExtended, +8.64e15); +assertEq(iso(maxDateExtended - 1), "+275760-09-12T23:59:59.999Z"); +assertEq(iso(maxDateExtended ), "+275760-09-13T00:00:00.000Z"); +assertThrowsInstanceOf(() => iso(maxDateExtended + 1), RangeError); + + +// Values around minimum date for extended iso format. +var minDateExtended = utc(-271821, 4, 20, 0, 0, 0, 0); +assertEq(minDateExtended, -8.64e15); +assertThrowsInstanceOf(() => iso(minDateExtended - 1), RangeError); +assertEq(iso(minDateExtended ), "-271821-04-20T00:00:00.000Z"); +assertEq(iso(minDateExtended + 1), "-271821-04-20T00:00:00.001Z"); + + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/toISOString.js b/js/src/tests/non262/Date/toISOString.js new file mode 100644 index 0000000000..9eb4129345 --- /dev/null +++ b/js/src/tests/non262/Date/toISOString.js @@ -0,0 +1,24 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +function throwsRangeError(t) { + try { + var date = new Date(); + date.setTime(t); + var r = date.toISOString(); + throw new Error("toISOString didn't throw, instead returned " + r); + } catch (err) { + assertEq(err instanceof RangeError, true, 'wrong error: ' + err); + return; + } + assertEq(0, 1, 'not good, nyan, nyan'); +} + +throwsRangeError(Infinity); +throwsRangeError(-Infinity); +throwsRangeError(NaN); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/toJSON-01.js b/js/src/tests/non262/Date/toJSON-01.js new file mode 100644 index 0000000000..4a756aab54 --- /dev/null +++ b/js/src/tests/non262/Date/toJSON-01.js @@ -0,0 +1,238 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +var gTestfile = 'toJSON-01.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 584811; +var summary = "Date.prototype.toJSON isn't to spec"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var called; + +var dateToJSON = Date.prototype.toJSON; +assertEq(Date.prototype.hasOwnProperty("toJSON"), true); +assertEq(typeof dateToJSON, "function"); + +// brief test to exercise this outside of isolation, just for sanity +var invalidDate = new Date(); +invalidDate.setTime(NaN); +assertEq(JSON.stringify({ p: invalidDate }), '{"p":null}'); + + +/* 15.9.5.44 Date.prototype.toJSON ( key ) */ +assertEq(dateToJSON.length, 1); + +/* + * 1. Let O be the result of calling ToObject, giving it the this value as its + * argument. + */ +try +{ + dateToJSON.call(null); + throw new Error("should have thrown a TypeError"); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, + "ToObject throws TypeError for null/undefined"); +} + +try +{ + dateToJSON.call(undefined); + throw new Error("should have thrown a TypeError"); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, + "ToObject throws TypeError for null/undefined"); +} + + +/* + * 2. Let tv be ToPrimitive(O, hint Number). + * ...expands to: + * 1. Let valueOf be the result of calling the [[Get]] internal method of object O with argument "valueOf". + * 2. If IsCallable(valueOf) is true then, + * a. Let val be the result of calling the [[Call]] internal method of valueOf, with O as the this value and + * an empty argument list. + * b. If val is a primitive value, return val. + * 3. Let toString be the result of calling the [[Get]] internal method of object O with argument "toString". + * 4. If IsCallable(toString) is true then, + * a. Let str be the result of calling the [[Call]] internal method of toString, with O as the this value and + * an empty argument list. + * b. If str is a primitive value, return str. + * 5. Throw a TypeError exception. + */ +try +{ + var r = dateToJSON.call({ get valueOf() { throw 17; } }); + throw new Error("didn't throw, returned: " + r); +} +catch (e) +{ + assertEq(e, 17, "bad exception: " + e); +} + +called = false; +assertEq(dateToJSON.call({ valueOf: null, + toString: function() { called = true; return 12; }, + toISOString: function() { return "ohai"; } }), + "ohai"); +assertEq(called, true); + +called = false; +assertEq(dateToJSON.call({ valueOf: function() { called = true; return 42; }, + toISOString: function() { return null; } }), + null); +assertEq(called, true); + +try +{ + called = false; + dateToJSON.call({ valueOf: function() { called = true; return {}; }, + get toString() { throw 42; } }); +} +catch (e) +{ + assertEq(called, true); + assertEq(e, 42, "bad exception: " + e); +} + +called = false; +assertEq(dateToJSON.call({ valueOf: function() { called = true; return {}; }, + get toString() { return function() { return 8675309; }; }, + toISOString: function() { return true; } }), + true); +assertEq(called, true); + +var asserted = false; +called = false; +assertEq(dateToJSON.call({ valueOf: function() { called = true; return {}; }, + get toString() + { + assertEq(called, true); + asserted = true; + return function() { return 8675309; }; + }, + toISOString: function() { return NaN; } }), + NaN); +assertEq(asserted, true); + +try +{ + var r = dateToJSON.call({ valueOf: null, toString: null, + get toISOString() + { + throw new Error("shouldn't have been gotten"); + } }); + throw new Error("didn't throw, returned: " + r); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, "bad exception: " + e); +} + + +/* 3. If tv is a Number and is not finite, return null. */ +assertEq(dateToJSON.call({ valueOf: function() { return Infinity; } }), null); +assertEq(dateToJSON.call({ valueOf: function() { return -Infinity; } }), null); +assertEq(dateToJSON.call({ valueOf: function() { return NaN; } }), null); + +assertEq(dateToJSON.call({ valueOf: function() { return Infinity; }, + toISOString: function() { return {}; } }), null); +assertEq(dateToJSON.call({ valueOf: function() { return -Infinity; }, + toISOString: function() { return []; } }), null); +assertEq(dateToJSON.call({ valueOf: function() { return NaN; }, + toISOString: function() { return undefined; } }), null); + + +/* + * 4. Let toISO be the result of calling the [[Get]] internal method of O with + * argument "toISOString". + */ +try +{ + var r = dateToJSON.call({ get toISOString() { throw 42; } }); + throw new Error("didn't throw, returned: " + r); +} +catch (e) +{ + assertEq(e, 42, "bad exception: " + e); +} + + +/* 5. If IsCallable(toISO) is false, throw a TypeError exception. */ +try +{ + var r = dateToJSON.call({ toISOString: null }); + throw new Error("didn't throw, returned: " + r); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, "bad exception: " + e); +} + +try +{ + var r = dateToJSON.call({ toISOString: undefined }); + throw new Error("didn't throw, returned: " + r); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, "bad exception: " + e); +} + +try +{ + var r = dateToJSON.call({ toISOString: "oogabooga" }); + throw new Error("didn't throw, returned: " + r); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, "bad exception: " + e); +} + +try +{ + var r = dateToJSON.call({ toISOString: Math.PI }); + throw new Error("didn't throw, returned: " + r); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, "bad exception: " + e); +} + + +/* + * 6. Return the result of calling the [[Call]] internal method of toISO with O + * as the this value and an empty argument list. + */ +var o = + { + toISOString: function(a) + { + called = true; + assertEq(this, o); + assertEq(a, undefined); + assertEq(arguments.length, 0); + return obj; + } + }; +var obj = {}; +called = false; +assertEq(dateToJSON.call(o), obj, "should have gotten obj back"); +assertEq(called, true); + + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Date/toPrimitive.js b/js/src/tests/non262/Date/toPrimitive.js new file mode 100644 index 0000000000..11346b1ae8 --- /dev/null +++ b/js/src/tests/non262/Date/toPrimitive.js @@ -0,0 +1,62 @@ +// ES6 20.3.4.45 Date.prototype[@@toPrimitive](hint) + +// The toPrimitive method throws if the this value isn't an object. +var toPrimitive = Date.prototype[Symbol.toPrimitive]; +assertThrowsInstanceOf(() => toPrimitive.call(undefined, "default"), TypeError); +assertThrowsInstanceOf(() => toPrimitive.call(3, "default"), TypeError); + +// It doesn't have to be a Date object, though. +var obj = { + toString() { return "str"; }, + valueOf() { return "val"; } +}; +assertEq(toPrimitive.call(obj, "number"), "val"); +assertEq(toPrimitive.call(obj, "string"), "str"); +assertEq(toPrimitive.call(obj, "default"), "str"); + +// It throws if the hint argument is missing or not one of the three allowed values. +assertThrowsInstanceOf(() => toPrimitive.call(obj), TypeError); +assertThrowsInstanceOf(() => toPrimitive.call(obj, undefined), TypeError); +assertThrowsInstanceOf(() => toPrimitive.call(obj, "boolean"), TypeError); +assertThrowsInstanceOf(() => toPrimitive.call(obj, ["number"]), TypeError); +assertThrowsInstanceOf(() => toPrimitive.call(obj, {toString() { throw "FAIL"; }}), TypeError); + +// The next few tests cover the OrdinaryToPrimitive algorithm, specified in +// ES6 7.1.1 ToPrimitive(input [, PreferredType]). + +// Date.prototype.toString or .valueOf can be overridden. +var dateobj = new Date(); +Date.prototype.toString = function () { + assertEq(this, dateobj); + return 14; +}; +Date.prototype.valueOf = function () { + return "92"; +}; +assertEq(dateobj[Symbol.toPrimitive]("number"), "92"); +assertEq(dateobj[Symbol.toPrimitive]("string"), 14); +assertEq(dateobj[Symbol.toPrimitive]("default"), 14); +assertEq(dateobj == 14, true); // equality comparison: passes "default" + +// If this.toString is a non-callable value, this.valueOf is called instead. +Date.prototype.toString = {}; +assertEq(dateobj[Symbol.toPrimitive]("string"), "92"); +assertEq(dateobj[Symbol.toPrimitive]("default"), "92"); + +// And vice versa. +Date.prototype.toString = function () { return 15; }; +Date.prototype.valueOf = "ponies"; +assertEq(dateobj[Symbol.toPrimitive]("number"), 15); + +// If neither is callable, it throws a TypeError. +Date.prototype.toString = "ponies"; +assertThrowsInstanceOf(() => dateobj[Symbol.toPrimitive]("default"), TypeError); + +// Surface features. +assertEq(toPrimitive.name, "[Symbol.toPrimitive]"); +var desc = Object.getOwnPropertyDescriptor(Date.prototype, Symbol.toPrimitive); +assertEq(desc.configurable, true); +assertEq(desc.enumerable, false); +assertEq(desc.writable, false); + +reportCompare(0, 0); diff --git a/js/src/tests/non262/Date/toString-generic.js b/js/src/tests/non262/Date/toString-generic.js new file mode 100644 index 0000000000..1e1c1fee93 --- /dev/null +++ b/js/src/tests/non262/Date/toString-generic.js @@ -0,0 +1,15 @@ +var BUGNUMBER = 861219; +var summary = 'Date.prototype.toString is a generic function'; + +// Revised in ECMA 2018, Date.prototype.toString is no longer generic (bug 1381433). + +print(BUGNUMBER + ": " + summary); + +for (var thisValue of [{}, [], /foo/, Date.prototype, new Proxy(new Date(), {})]) + assertThrowsInstanceOf(() => Date.prototype.toString.call(thisValue), TypeError); + +for (var prim of [null, undefined, 0, 1.2, true, false, "foo", Symbol.iterator]) + assertThrowsInstanceOf(() => Date.prototype.toString.call(prim), TypeError); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/toString-localized-posix.js b/js/src/tests/non262/Date/toString-localized-posix.js new file mode 100644 index 0000000000..b2314f60a5 --- /dev/null +++ b/js/src/tests/non262/Date/toString-localized-posix.js @@ -0,0 +1,71 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) -- Requires ICU time zone support + +// Date.prototype.toString includes a localized time zone name comment. + +// Repeats the test from "toString-localized.js", but uses POSIX instead of IANA +// names for the time zones. This allows to run these tests on Windows, too. + +inTimeZone("PST8PDT", () => { + let dt = new Date(2018, Month.July, 14); + + withLocale("en", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT-0700 (Pacific Daylight Time)"); + }); + withLocale("fr", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT-0700 (heure d’été du Pacifique nord-américain)"); + }); + withLocale("de", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT-0700 (Nordamerikanische Westküsten-Sommerzeit)"); + }); + withLocale("ar", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT-0700 (توقيت المحيط الهادي الصيفي)"); + }); + withLocale("zh", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT-0700 (北美太平洋夏令时间)"); + }); +}); + +for (let tz of ["UTC", "UCT"]) { + inTimeZone(tz, () => { + let dt = new Date(2018, Month.July, 14); + + withLocale("en", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (Coordinated Universal Time)"); + }); + withLocale("fr", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (temps universel coordonné)"); + }); + withLocale("de", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (Koordinierte Weltzeit)"); + }); + withLocale("ar", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (التوقيت العالمي المنسق)"); + }); + withLocale("zh", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (协调世界时)"); + }); + }); +} + +inTimeZone("GMT", () => { + let dt = new Date(2018, Month.July, 14); + + withLocale("en", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (Greenwich Mean Time)"); + }); + withLocale("fr", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (heure moyenne de Greenwich)"); + }); + withLocale("de", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (Mittlere Greenwich-Zeit)"); + }); + withLocale("ar", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (توقيت غرينتش)"); + }); + withLocale("zh", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (格林尼治标准时间)"); + }); +}); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/toString-localized.js b/js/src/tests/non262/Date/toString-localized.js new file mode 100644 index 0000000000..6baa535e5e --- /dev/null +++ b/js/src/tests/non262/Date/toString-localized.js @@ -0,0 +1,90 @@ +// |reftest| skip-if(xulRuntime.OS=="WINNT"||!this.hasOwnProperty("Intl")) -- Windows doesn't accept IANA names for the TZ env variable; Requires ICU time zone support + +// Date.prototype.toString includes a localized time zone name comment. + +inTimeZone("Europe/Paris", () => { + let dt = new Date(2018, Month.July, 14); + + withLocale("en", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0200 (Central European Summer Time)"); + }); + withLocale("fr", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0200 (heure d’été d’Europe centrale)"); + }); + withLocale("de", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0200 (Mitteleuropäische Sommerzeit)"); + }); + withLocale("ar", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0200 (توقيت وسط أوروبا الصيفي)"); + }); + withLocale("zh", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0200 (中欧夏令时间)"); + }); +}); + +inTimeZone("America/Los_Angeles", () => { + let dt = new Date(2018, Month.July, 14); + + withLocale("en", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT-0700 (Pacific Daylight Time)"); + }); + withLocale("fr", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT-0700 (heure d’été du Pacifique nord-américain)"); + }); + withLocale("de", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT-0700 (Nordamerikanische Westküsten-Sommerzeit)"); + }); + withLocale("ar", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT-0700 (توقيت المحيط الهادي الصيفي)"); + }); + withLocale("zh", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT-0700 (北美太平洋夏令时间)"); + }); +}); + +for (let tz of ["UTC", "UCT", "Zulu", "Universal", "Etc/UTC", "Etc/UCT", "Etc/Zulu", "Etc/Universal"]) { + inTimeZone(tz, () => { + let dt = new Date(2018, Month.July, 14); + + withLocale("en", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (Coordinated Universal Time)"); + }); + withLocale("fr", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (temps universel coordonné)"); + }); + withLocale("de", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (Koordinierte Weltzeit)"); + }); + withLocale("ar", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (التوقيت العالمي المنسق)"); + }); + withLocale("zh", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (协调世界时)"); + }); + }); +} + +for (let tz of ["GMT", "Etc/GMT"]) { + inTimeZone(tz, () => { + let dt = new Date(2018, Month.July, 14); + + withLocale("en", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (Greenwich Mean Time)"); + }); + withLocale("fr", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (heure moyenne de Greenwich)"); + }); + withLocale("de", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (Mittlere Greenwich-Zeit)"); + }); + withLocale("ar", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (توقيت غرينتش)"); + }); + withLocale("zh", () => { + assertDateTime(dt, "Sat Jul 14 2018 00:00:00 GMT+0000 (格林尼治标准时间)"); + }); + }); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Date/two-digit-years.js b/js/src/tests/non262/Date/two-digit-years.js new file mode 100644 index 0000000000..80cbc2ecef --- /dev/null +++ b/js/src/tests/non262/Date/two-digit-years.js @@ -0,0 +1,71 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommonn.org/licenses/publicdomain/ + */ + +/* + * For the sake of cross compatibility with other implementations we + * implement date parsing heuristics which support single and double + * digit years. See bug: 1265136 + */ + +/************** + * BEGIN TEST * + **************/ + +for (let year of Array(100).keys()) { + for (let month of Array(12).keys()) { + for (let day of Array(31).keys()) { + let fullYear = year >= 50 ? year + 1900 : year + 2000; + let fullDate = new Date(`${month + 1}/${day + 1}/${fullYear}`); + + // mm/dd/yy + let d1 = new Date(`${month + 1}/${day + 1}/${year}`); + assertEq(d1.getTime(), fullDate.getTime()) + + // yy/mm/dd + let d2 = new Date(`${year}/${month + 1}/${day + 1}`); + if (year > 31) { + assertEq(d2.getTime(), fullDate.getTime()) + } else if (year > 12) { + assertEq(d2.getTime(), new Date(NaN).getTime()) + } + } + } +} + +assertEq(new Date("99/1/99").getTime(), new Date(NaN).getTime()); +assertEq(new Date("13/13/13").getTime(), new Date(NaN).getTime()); +assertEq(new Date("0/10/0").getTime(), new Date(NaN).getTime()); + +// Written months. +for (let year of Array(1000).keys()) { + let fullDate = new Date(`5/1/${year}`); + let d1 = new Date(`may 1 ${year}`); + let d2 = new Date(`1 may ${year}`); + let d3 = new Date(`1 ${year} may`); + + assertEq(d1.getTime(), fullDate.getTime()) + assertEq(d2.getTime(), fullDate.getTime()) + assertEq(d3.getTime(), fullDate.getTime()) + + if (year > 31) { + let d4 = new Date(`may ${year} 1`); + let d5 = new Date(`${year} may 1`); + let d6 = new Date(`${year} 1 may`); + + assertEq(d4.getTime(), fullDate.getTime()) + assertEq(d5.getTime(), fullDate.getTime()) + assertEq(d6.getTime(), fullDate.getTime()) + } +} + +assertEq(new Date("may 1999 1999").getTime(), new Date(NaN).getTime()); +assertEq(new Date("may 0 0").getTime(), new Date(NaN).getTime()); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Error/AggregateError.js b/js/src/tests/non262/Error/AggregateError.js new file mode 100644 index 0000000000..d4b4420d67 --- /dev/null +++ b/js/src/tests/non262/Error/AggregateError.js @@ -0,0 +1,80 @@ +assertEq(typeof AggregateError, "function"); +assertEq(Object.getPrototypeOf(AggregateError), Error); +assertEq(AggregateError.name, "AggregateError"); +assertEq(AggregateError.length, 2); + +assertEq(Object.getPrototypeOf(AggregateError.prototype), Error.prototype); +assertEq(AggregateError.prototype.name, "AggregateError"); +assertEq(AggregateError.prototype.message, ""); + +// The |errors| argument is mandatory. +assertThrowsInstanceOf(() => new AggregateError(), TypeError); +assertThrowsInstanceOf(() => AggregateError(), TypeError); + +// The .errors data property is an array object. +{ + let err = new AggregateError([]); + + let {errors} = err; + assertEq(Array.isArray(errors), true); + assertEq(errors.length, 0); + + // The errors object is modifiable. + errors.push(123); + assertEq(errors.length, 1); + assertEq(errors[0], 123); + assertEq(err.errors[0], 123); + + // The property is writable. + err.errors = undefined; + assertEq(err.errors, undefined); +} + +// The errors argument can be any iterable. +{ + function* g() { yield* [1, 2, 3]; } + + let {errors} = new AggregateError(g()); + assertEqArray(errors, [1, 2, 3]); +} + +// The message property is populated by the second argument. +{ + let err; + + err = new AggregateError([]); + assertEq(err.message, ""); + + err = new AggregateError([], "my message"); + assertEq(err.message, "my message"); +} + +{ + assertEq("errors" in AggregateError.prototype, false); + + const { + configurable, + enumerable, + value, + writable + } = Object.getOwnPropertyDescriptor(new AggregateError([]), "errors"); + assertEq(configurable, true); + assertEq(enumerable, false); + assertEq(writable, true); + assertEq(value.length, 0); + + const g = newGlobal(); + + let obj = {}; + let errors = new g.AggregateError([obj]).errors; + + assertEq(errors.length, 1); + assertEq(errors[0], obj); + + // The prototype is |g.Array.prototype| in the cross-compartment case. + let proto = Object.getPrototypeOf(errors); + assertEq(proto === g.Array.prototype, true); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Error/browser.js b/js/src/tests/non262/Error/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Error/constructor-ordering.js b/js/src/tests/non262/Error/constructor-ordering.js new file mode 100644 index 0000000000..dbcc2e6048 --- /dev/null +++ b/js/src/tests/non262/Error/constructor-ordering.js @@ -0,0 +1,17 @@ +var order = 0; +function assertOrdering(ordering) { + assertEq(order, ordering); + order++; +} + +// Spec mandates that the prototype is looked up /before/ we toString the +// argument. +var handler = { get() { assertOrdering(0); return Error.prototype } }; +var errorProxy = new Proxy(Error, handler); + +var toStringable = { toString() { assertOrdering(1); return "Argument"; } }; + +new errorProxy(toStringable); + +if (typeof reportCompare === 'function') + reportCompare(0,0,"OK"); diff --git a/js/src/tests/non262/Error/constructor-proto.js b/js/src/tests/non262/Error/constructor-proto.js new file mode 100644 index 0000000000..4ddc6025e8 --- /dev/null +++ b/js/src/tests/non262/Error/constructor-proto.js @@ -0,0 +1,17 @@ +const nativeErrors = [ + InternalError, + EvalError, + RangeError, + ReferenceError, + SyntaxError, + TypeError, + URIError +]; + +assertEq(Reflect.getPrototypeOf(Error), Function.prototype) + +for (const error of nativeErrors) + assertEq(Reflect.getPrototypeOf(error), Error); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Error/prototype-properties.js b/js/src/tests/non262/Error/prototype-properties.js new file mode 100644 index 0000000000..16264bc56d --- /dev/null +++ b/js/src/tests/non262/Error/prototype-properties.js @@ -0,0 +1,26 @@ +const nativeErrors = [ + InternalError, + EvalError, + RangeError, + ReferenceError, + SyntaxError, + TypeError, + URIError +]; + +const expectedOwnKeys = "toSource" in Object.prototype + ? "toSource,toString,message,name,stack,constructor" + : "toString,message,name,stack,constructor"; +assertEq(Reflect.ownKeys(Error.prototype).toString(), expectedOwnKeys); +assertEq(Error.prototype.name, "Error"); +assertEq(Error.prototype.message, ""); + +for (const error of nativeErrors) { + assertEq(Reflect.ownKeys(error.prototype).toString(), "message,name,constructor"); + assertEq(error.prototype.name, error.name); + assertEq(error.prototype.message, ""); + assertEq(error.prototype.constructor, error); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Error/prototype.js b/js/src/tests/non262/Error/prototype.js new file mode 100644 index 0000000000..b22a8e084b --- /dev/null +++ b/js/src/tests/non262/Error/prototype.js @@ -0,0 +1,18 @@ +const nativeErrors = [ + InternalError, + EvalError, + RangeError, + ReferenceError, + SyntaxError, + TypeError, + URIError +]; + +assertEq(Reflect.getPrototypeOf(Error.prototype), Object.prototype) + +for (const error of nativeErrors) { + assertEq(Reflect.getPrototypeOf(error.prototype), Error.prototype); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Error/regress-354246.js b/js/src/tests/non262/Error/regress-354246.js new file mode 100644 index 0000000000..644bcba106 --- /dev/null +++ b/js/src/tests/non262/Error/regress-354246.js @@ -0,0 +1,34 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 354246; +var summary = 'calling Error constructor with object with bad toString'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + expect = '13'; + + actual += '1'; + try + { + new Error({toString: function() { x.y } }); + } + catch(e) + { + } + actual += '3'; + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/Error/regress-412324.js b/js/src/tests/non262/Error/regress-412324.js new file mode 100644 index 0000000000..d9debaa896 --- /dev/null +++ b/js/src/tests/non262/Error/regress-412324.js @@ -0,0 +1,17 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 412324; +var summary = 'Allow function Error(){} for the love of Pete'; +var actual = 'No Error'; +var expect = 'No Error'; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +function Error() {} + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/Error/regress-465377.js b/js/src/tests/non262/Error/regress-465377.js new file mode 100644 index 0000000000..ea7be79f98 --- /dev/null +++ b/js/src/tests/non262/Error/regress-465377.js @@ -0,0 +1,78 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465377; +var summary = 'instanceof relations between Error objects'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + expect = actual = 'No Exception'; + + try + { + var list = [ + "Error", + "InternalError", + "EvalError", + "RangeError", + "ReferenceError", + "SyntaxError", + "TypeError", + "URIError" + ]; + var instances = []; + + for (var i = 0; i != list.length; ++i) { + var name = list[i]; + var constructor = this[name]; + var tmp = constructor.name; + if (tmp !== name) + throw "Bad value for "+name+".name: "+String(tmp); + instances[i] = new constructor(); + } + + for (var i = 0; i != instances.length; ++i) { + var instance = instances[i]; + var name = instance.name; + var constructor = instance.constructor; + var tmp = constructor.name; + if (constructor !== this[name]) + throw "Bad value of (new "+name+").constructor: "+String(tmp); + if (tmp !== name) + throw "Bad value for constructor.name: "+String(tmp); + if (!(instance instanceof Object)) + throw "Bad instanceof Object for "+name; + if (!(instance instanceof Error)) + throw "Bad instanceof Error for "+name; + if (!(instance instanceof constructor)) + throw "Bad instanceof constructor for "+name; + if (instance instanceof Function) + throw "Bad instanceof Function for "+name; + for (var j = 1; j != instances.length; ++j) { + if (i != j && instance instanceof instances[j].constructor) { + throw "Unexpected (new "+name+") instanceof "+ instances[j].name; + } + } + } + + print("OK"); + } + catch(ex) + { + actual = ex + ''; + } + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/Error/shell.js b/js/src/tests/non262/Error/shell.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Exceptions/browser.js b/js/src/tests/non262/Exceptions/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Exceptions/catchguard-002-n.js b/js/src/tests/non262/Exceptions/catchguard-002-n.js new file mode 100644 index 0000000000..fa574389db --- /dev/null +++ b/js/src/tests/non262/Exceptions/catchguard-002-n.js @@ -0,0 +1,31 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +DESCRIPTION = "var in catch clause should have caused an error."; + +var expect; +var actual; + +test(); + +function test() +{ + var EXCEPTION_DATA = "String exception"; + var e; + + printStatus ("Catchguard var declaration negative test."); + + try + { + throw EXCEPTION_DATA; + } + catch (var e) + { + actual = e + ''; + } + + reportCompare(expect, actual, DESCRIPTION); +} diff --git a/js/src/tests/non262/Exceptions/catchguard-003-n.js b/js/src/tests/non262/Exceptions/catchguard-003-n.js new file mode 100644 index 0000000000..a45b56adca --- /dev/null +++ b/js/src/tests/non262/Exceptions/catchguard-003-n.js @@ -0,0 +1,35 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +DESCRIPTION = "Illegally constructed catchguard should have thrown an exception."; + +var expect; +var actual; + +test(); + +function test() +{ + var EXCEPTION_DATA = "String exception"; + var e; + + printStatus ("Catchguard syntax negative test #2."); + + try + { + throw EXCEPTION_DATA; + } + catch (e) + { + actual = e + ': 1'; + } + catch (e) /* two non-guarded catch statements should generate an error */ + { + actual = e + ': 2'; + } + + reportCompare(expect, actual, DESCRIPTION); +} diff --git a/js/src/tests/non262/Exceptions/error-expando-reconfigure.js b/js/src/tests/non262/Exceptions/error-expando-reconfigure.js new file mode 100644 index 0000000000..c70ff5f853 --- /dev/null +++ b/js/src/tests/non262/Exceptions/error-expando-reconfigure.js @@ -0,0 +1,28 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = "error-expando-reconfigure.js" +//----------------------------------------------------------------------------- +var BUGNUMBER = 961494; +var summary = + "Reconfiguring the first expando property added to an Error object " + + "shouldn't assert"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var err = new Error(); // no message argument => no err.message property +err.expando = 17; +Object.defineProperty(err, "expando", { configurable: false }); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Exceptions/error-property-enumerability.js b/js/src/tests/non262/Exceptions/error-property-enumerability.js new file mode 100644 index 0000000000..c6674cfc57 --- /dev/null +++ b/js/src/tests/non262/Exceptions/error-property-enumerability.js @@ -0,0 +1,30 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var errors = ["Error", "EvalError", "RangeError", "ReferenceError", + "SyntaxError", "TypeError", "URIError"]; + +for (var i = 0; i < errors.length; i++) { + var error = this[errors[i]]; + + var desc = Object.getOwnPropertyDescriptor(error.prototype, "name"); + assertEq(!!desc, true, errors[i] + ".prototype.name should exist"); + assertEq((desc || {}).enumerable, false, errors[i] + ".prototype.name should not be enumerable"); + + desc = Object.getOwnPropertyDescriptor(error.prototype, "message"); + assertEq(!!desc, true, errors[i] + ".prototype.message should exist"); + assertEq((desc || {}).enumerable, false, errors[i] + ".prototype.message should not be enumerable"); + + var instance = new error; + desc = Object.getOwnPropertyDescriptor(instance, "message"); + assertEq(!!desc, false, "new " + errors[i] + ".message should not exist"); + + instance = new error("a message"); + desc = Object.getOwnPropertyDescriptor(instance, "message"); + assertEq(!!desc, true, "new " + errors[i] + "(...).message should exist"); + assertEq((desc || {}).enumerable, false, "new " + errors[i] + "(...).message should not be enumerable"); +} + +reportCompare(true, true); diff --git a/js/src/tests/non262/Exceptions/errstack-001.js b/js/src/tests/non262/Exceptions/errstack-001.js new file mode 100644 index 0000000000..042e357fa6 --- /dev/null +++ b/js/src/tests/non262/Exceptions/errstack-001.js @@ -0,0 +1,242 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * + * Date: 28 Feb 2002 + * SUMMARY: Testing that Error.stack distinguishes between: + * + * A) top-level calls: myFunc(); + * B) no-name function calls: function() { myFunc();} () + * + * The stack frame for A) should begin with '@' + * The stack frame for B) should begin with '()' + * + * This behavior was coded by Brendan during his fix for bug 127136. + * See http://bugzilla.mozilla.org/show_bug.cgi?id=127136#c13 + * + * Note: our function getStackFrames(err) orders the array of stack frames + * so that the 0th element will correspond to the highest frame, i.e. will + * correspond to a line in top-level code. The 1st element will correspond + * to the function that is called first, and so on... + * + * NOTE: At present Rhino does not have an Error.stack property. It is an + * ECMA extension, see http://bugzilla.mozilla.org/show_bug.cgi?id=123177 + */ +//----------------------------------------------------------------------------- +var UBound = 0; +var BUGNUMBER = '(none)'; +var summary = 'Testing Error.stack'; +var status = ''; +var statusitems = []; +var actual = ''; +var actualvalues = []; +var expect= ''; +var expectedvalues = []; +var myErr = ''; +var stackFrames = ''; + + +function A(x,y) +{ + return B(x+1,y+1); +} + +function B(x,z) +{ + return C(x+1,z+1); +} + +function C(x,y) +{ + return D(x+1,y+1); +} + +function D(x,z) +{ + try + { + throw new Error('meep!'); + } + catch (e) + { + return e; + } +} + + +myErr = A(44,13); +stackFrames = getStackFrames(myErr); +status = inSection(1); +actual = stackFrames[0].substring(0,1); +expect = '@'; +addThis(); + +status = inSection(2); +actual = stackFrames[1].substring(0,2); +expect = 'A@'; +addThis(); + +status = inSection(3); +actual = stackFrames[2].substring(0,2); +expect = 'B@'; +addThis(); + +status = inSection(4); +actual = stackFrames[3].substring(0,2); +expect = 'C@'; +addThis(); + +status = inSection(5); +actual = stackFrames[4].substring(0,2); +expect = 'D@'; +addThis(); + + + +myErr = A('44:foo','13:bar'); +stackFrames = getStackFrames(myErr); +status = inSection(6); +actual = stackFrames[0].substring(0,1); +expect = '@'; +addThis(); + +status = inSection(7); +actual = stackFrames[1].substring(0,2); +expect = 'A@'; +addThis(); + +status = inSection(8); +actual = stackFrames[2].substring(0,2); +expect = 'B@'; +addThis(); + +status = inSection(9); +actual = stackFrames[3].substring(0,2); +expect = 'C@'; +addThis(); + +status = inSection(10); +actual = stackFrames[4].substring(0,2); +expect = 'D@';; +addThis(); + + + +/* + * Make the first frame occur in a function with an empty name - + */ +myErr = function() { return A(44,13); } (); +stackFrames = getStackFrames(myErr); +status = inSection(11); +actual = stackFrames[0].substring(0,1); +expect = '@'; +addThis(); + +status = inSection(12); +actual = stackFrames[1].substring(0,7); +expect = 'myErr<@'; +addThis(); + +status = inSection(13); +actual = stackFrames[2].substring(0,2); +expect = 'A@'; +addThis(); + +// etc. for the rest of the frames as above + + + +/* + * Make the first frame occur in a function with name 'anonymous' - + */ +var f = Function('return A(44,13);'); +myErr = f(); +stackFrames = getStackFrames(myErr); +status = inSection(14); +actual = stackFrames[0].substring(0,1); +expect = '@'; +addThis(); + +status = inSection(15); +actual = stackFrames[1].substring(0,10); +expect = 'anonymous@'; +addThis(); + +status = inSection(16); +actual = stackFrames[2].substring(0,2); +expect = 'A@'; +addThis(); + +// etc. for the rest of the frames as above + + + +/* + * Make a user-defined error via the Error() function - + */ +var message = 'Hi there!'; var fileName = 'file name'; var lineNumber = 0; +myErr = Error(message, fileName, lineNumber); +stackFrames = getStackFrames(myErr); +status = inSection(17); +actual = stackFrames[0].substring(0,1); +expect = '@'; +addThis(); + + +/* + * Now use the |new| keyword. Re-use the same params - + */ +myErr = new Error(message, fileName, lineNumber); +stackFrames = getStackFrames(myErr); +status = inSection(18); +actual = stackFrames[0].substring(0,1); +expect = '@'; +addThis(); + + + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + + +/* + * Split the string |err.stack| along its '\n' delimiter. + * As of 2002-02-28 |err.stack| ends with the delimiter, so + * the resulting array has an empty string as its last element. + * + * Pop that useless element off before doing anything. + * Then reverse the array, for convenience of indexing - + */ +function getStackFrames(err) +{ + var arr = err.stack.split('\n'); + arr.pop(); + return arr.reverse(); +} + + +function addThis() +{ + statusitems[UBound] = status; + actualvalues[UBound] = actual; + expectedvalues[UBound] = expect; + UBound++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus(summary); + + for (var i=0; i0. The bug was filed because we + * were getting i===0; i.e. |i| did not retain the value it had at the + * location of the error. + * + */ +//----------------------------------------------------------------------------- +var UBound = 0; +var BUGNUMBER = 121658; +var msg = '"Too much recursion" errors should be safely caught by try...catch'; +var TEST_PASSED = 'i retained the value it had at location of error'; +var TEST_FAILED = 'i did NOT retain this value'; +var status = ''; +var statusitems = []; +var actual = ''; +var actualvalues = []; +var expect= ''; +var expectedvalues = []; +var i; + + +function f() +{ + ++i; + + // try...catch should catch the "too much recursion" error to ensue + try + { + f(); + } + catch(e) + { + } +} + +i=0; +f(); +status = inSection(1); +actual = (i>0); +expect = true; +addThis(); + + + +// Now try in function scope - +function g() +{ + f(); +} + +i=0; +g(); +status = inSection(2); +actual = (i>0); +expect = true; +addThis(); + + + +// Now try in eval scope - +var sEval = 'function h(){++i; try{h();} catch(e){}}; i=0; h();'; +eval(sEval); +status = inSection(3); +actual = (i>0); +expect = true; +addThis(); + + + +// Try in eval scope and mix functions up - +sEval = 'function a(){++i; try{h();} catch(e){}}; i=0; a();'; +eval(sEval); +status = inSection(4); +actual = (i>0); +expect = true; +addThis(); + + + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + + +function addThis() +{ + statusitems[UBound] = status; + actualvalues[UBound] = formatThis(actual); + expectedvalues[UBound] = formatThis(expect); + UBound++; +} + + +function formatThis(bool) +{ + return bool? TEST_PASSED : TEST_FAILED; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus(msg); + + for (var i=0; i -1); + expect = true; + addThis(); +} + + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + +function addThis() +{ + statusitems[UBound] = status; + actualvalues[UBound] = isReferenceError(actual); + expectedvalues[UBound] = isReferenceError(expect); + UBound++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + for (var i = 0; i < UBound; i++) + { + reportCompare(expectedvalues[i], actualvalues[i], statusitems[i]); + } +} + + +// converts a Boolean result into a textual result - +function isReferenceError(bResult) +{ + return bResult? msgERR_REF_YES : msgERR_REF_NO; +} diff --git a/js/src/tests/non262/Exceptions/shell.js b/js/src/tests/non262/Exceptions/shell.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Function/10.1.6-01.js b/js/src/tests/non262/Function/10.1.6-01.js new file mode 100644 index 0000000000..fbb98616e1 --- /dev/null +++ b/js/src/tests/non262/Function/10.1.6-01.js @@ -0,0 +1,29 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 293782; +var summary = 'Local variables should not be enumerable properties of the function'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +function f() +{ + var x,y + } + +var p; +actual = ''; + +for (p in f) +{ + actual += p + ','; +} +expect = ''; + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/Function/10.1.6.js b/js/src/tests/non262/Function/10.1.6.js new file mode 100644 index 0000000000..504001cb1a --- /dev/null +++ b/js/src/tests/non262/Function/10.1.6.js @@ -0,0 +1,23 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 293782; +var summary = 'Local variables can cause predefined function object properties to be undefined'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +function f() +{ + var name=1; +} + +expect = 'f'; +actual = f.name; + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/Function/10.2.1.1.6.js b/js/src/tests/non262/Function/10.2.1.1.6.js new file mode 100644 index 0000000000..69613386cd --- /dev/null +++ b/js/src/tests/non262/Function/10.2.1.1.6.js @@ -0,0 +1,35 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +function strictThis() { 'use strict'; return this; } + +/* Check that calls of flat closure slots get the right |this|. */ +function flat(g) { + function h() { return g(); } + return h; +} +assertEq(flat(strictThis)(), undefined); + +/* Check that calls up upvars get the right |this|. */ +function upvar(f) { + function h() { + return f(); + } + return h(); +} +assertEq(upvar(strictThis), undefined); + +/* Check that calls to with-object properties get an appropriate 'this'. */ +var obj = { f: strictThis }; +with (obj) { + /* + * The method won't compile anything containing a 'with', but it can + * compile 'g'. + */ + function g() { return f(); } + assertEq(g(), obj); +} + +reportCompare(true, true); diff --git a/js/src/tests/non262/Function/15.3.4.3-01.js b/js/src/tests/non262/Function/15.3.4.3-01.js new file mode 100644 index 0000000000..955d773766 --- /dev/null +++ b/js/src/tests/non262/Function/15.3.4.3-01.js @@ -0,0 +1,245 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: + * Jeff Walden + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 562448; +var summary = 'Function.prototype.apply should accept any arraylike arguments'; +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function expectTypeError(fun, msg) +{ + try + { + fun(); + assertEq(true, false, "should have thrown a TypeError"); + } + catch (e) + { + assertEq(e instanceof TypeError, true, msg + "; instead threw " + e); + } +} + +function fun() { } + +var global = this; + + +/* Step 1. */ +var nonfuns = [null, 1, -1, 2.5, "[[Call]]", undefined, true, false, {}]; +for (var i = 0, sz = nonfuns.length; i < sz; i++) +{ + var f = function() + { + Function.prototype.apply.apply(nonfuns[i], [1, 2, 3]); + }; + var msg = + "expected TypeError calling Function.prototype.apply with uncallable this"; + expectTypeError(f, msg); +} + + +/* Step 2. */ +var thisObj = {}; + +var currentThis, currentThisBox; +function funLength() +{ + assertEq(arguments.length, 0, "should have been called with no arguments"); + assertEq(this, currentThis, "wrong this"); +} +function strictFunLength() +{ + "use strict"; + assertEq(arguments.length, 0, "should have been called with no arguments"); + assertEq(this, currentThis, "wrong this"); +} + +currentThis = global; +funLength.apply(); +funLength.apply(undefined); +funLength.apply(undefined, undefined); +funLength.apply(undefined, null); + +currentThis = undefined; +strictFunLength.apply(); +strictFunLength.apply(undefined); +strictFunLength.apply(undefined, undefined); +strictFunLength.apply(undefined, null); + +currentThis = null; +strictFunLength.apply(null); +strictFunLength.apply(null, undefined); +strictFunLength.apply(null, null); + +currentThis = thisObj; +funLength.apply(thisObj); +funLength.apply(thisObj, null); +funLength.apply(thisObj, undefined); +strictFunLength.apply(thisObj); +strictFunLength.apply(thisObj, null); +strictFunLength.apply(thisObj, undefined); + +currentThis = 17; +strictFunLength.apply(17); +strictFunLength.apply(17, null); +strictFunLength.apply(17, undefined); + +function funThisPrimitive() +{ + assertEq(arguments.length, 0, "should have been called with no arguments"); + assertEq(this instanceof currentThisBox, true, + "this not instanceof " + currentThisBox); + assertEq(this.valueOf(), currentThis, + "wrong this valueOf()"); +} + +currentThis = 17; +currentThisBox = Number; +funThisPrimitive.apply(17); +funThisPrimitive.apply(17, undefined); +funThisPrimitive.apply(17, null); + +currentThis = "foopy"; +currentThisBox = String; +funThisPrimitive.apply("foopy"); +funThisPrimitive.apply("foopy", undefined); +funThisPrimitive.apply("foopy", null); + +currentThis = false; +currentThisBox = Boolean; +funThisPrimitive.apply(false); +funThisPrimitive.apply(false, undefined); +funThisPrimitive.apply(false, null); + + +/* Step 3. */ +var nonobjs = [1, -1, 2.5, "[[Call]]", true, false]; +for (var i = 0, sz = nonobjs.length; i < sz; i++) +{ + var f = function() { fun.apply(thisObj, nonobjs[i]); }; + var msg = "should have thrown a TypeError with non-object arguments"; + expectTypeError(f, msg); +} + + +/* Step 4. */ +var args = { get length() { throw 42; } }; +try +{ + fun.apply(thisObj, args); +} +catch (e) +{ + assertEq(e, 42, "didn't throw result of [[Get]] on arguments object"); +} + + +/* + * NB: There was an erratum removing the steps numbered 5 and 7 in the original + * version of ES5; see also the comments in js_fun_apply. + */ + +/* Step 5. */ +var called = false; +var argsObjectLength = + { length: { valueOf: function() { called = true; return 17; } } }; + +fun.apply({}, argsObjectLength); +assertEq(called, true, "should have been set in valueOf called via ToUint32"); + +var upvar = "unset"; +var argsObjectPrimitiveLength = + { + length: + { + valueOf: function() { upvar = "valueOf"; return {}; }, + toString: function() + { + upvar = upvar === "valueOf" ? "both" : "toString"; + return 17; + } + } + }; +fun.apply({}, argsObjectPrimitiveLength); +assertEq(upvar, "both", "didn't call all hooks properly"); + + +/* Step 6-9. */ +var seenThis, res, steps; +var argsAccessors = + { + length: 4, + get 0() { steps.push("0"); return 1; }, + get 1() { steps.push("1"); return 2; }, + // make sure values shine through holes + get 3() { steps.push("3"); return 8; }, + }; + +Object.prototype[2] = 729; + +seenThis = "not seen"; +function argsAsArray() +{ + seenThis = this; + steps.push(Math.PI); + return Array.prototype.map.call(arguments, function(v) { return v; }); +} + +steps = []; +res = argsAsArray.apply(thisObj, argsAccessors); +assertEq(seenThis, thisObj, "saw wrong this"); + +assertEq(steps.length, 4, "wrong steps: " + steps); +assertEq(steps[0], "0", "bad step 0"); +assertEq(steps[1], "1", "bad step 1"); +assertEq(steps[2], "3", "bad step 3"); +assertEq(steps[3], Math.PI, "bad last step"); + +assertEq(res.length, 4, "wrong return: " + res); +assertEq(res[0], 1, "wrong ret[0]"); +assertEq(res[1], 2, "wrong ret[0]"); +assertEq(res[2], 729, "wrong ret[0]"); +assertEq(res[3], 8, "wrong ret[0]"); + +seenThis = "not seen"; +function strictArgsAsArray() +{ + "use strict"; + seenThis = this; + steps.push(NaN); + return Array.prototype.map.call(arguments, function(v) { return v; }); +} + +steps = []; +res = strictArgsAsArray.apply(null, argsAccessors); +assertEq(seenThis, null, "saw wrong this"); + +assertEq(steps.length, 4, "wrong steps: " + steps); +assertEq(steps[0], "0", "bad step 0"); +assertEq(steps[1], "1", "bad step 1"); +assertEq(steps[2], "3", "bad step 3"); +assertEq(steps[3], 0 / 0, "bad last step"); + +assertEq(res.length, 4, "wrong return: " + res); +assertEq(res[0], 1, "wrong ret[0]"); +assertEq(res[1], 2, "wrong ret[0]"); +assertEq(res[2], 729, "wrong ret[0]"); +assertEq(res[3], 8, "wrong ret[0]"); + +strictArgsAsArray.apply(17, argsAccessors); +assertEq(seenThis, 17, "saw wrong this"); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Function/Function-arguments-gc.js b/js/src/tests/non262/Function/Function-arguments-gc.js new file mode 100644 index 0000000000..2504523362 --- /dev/null +++ b/js/src/tests/non262/Function/Function-arguments-gc.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(Android) +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: + * Christian Holler + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 623301; +var summary = "Properly root argument names during Function()"; +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +if (typeof gczeal === "function") + gczeal(2); + +function crashMe(n) +{ + var nasty = []; + while (n--) + nasty.push("a" + n); + return Function.apply(null, nasty); +} + +var count = 64; // exact value not important +assertEq(crashMe(count + 1).length, count); + +if (typeof gczeal === "function") + gczeal(0); // reset + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Function/Function-prototype.js b/js/src/tests/non262/Function/Function-prototype.js new file mode 100644 index 0000000000..218b1d54ca --- /dev/null +++ b/js/src/tests/non262/Function/Function-prototype.js @@ -0,0 +1,11 @@ +var desc = Object.getOwnPropertyDescriptor(Function.prototype, "length"); +assertDeepEq(desc, + {value: 0, writable: false, enumerable: false, configurable: true}); + +assertEq(Function.prototype.prototype, undefined); +assertEq(Function.prototype.callee, undefined); +assertThrowsInstanceOf(() => Function.prototype.caller, TypeError); +assertThrowsInstanceOf(() => Function.prototype.arguments, TypeError); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Function/Function-with-eval.js b/js/src/tests/non262/Function/Function-with-eval.js new file mode 100644 index 0000000000..981abf2d04 --- /dev/null +++ b/js/src/tests/non262/Function/Function-with-eval.js @@ -0,0 +1,25 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +assertEq(new Function( + "eval('var foo = 915805');" + + "return foo;" + )(), + 915805); + +assertEq(new Function( + "eval('function foo() {" + + "return 915805;" + + "}');" + + "return foo;" + )()(), + 915805); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Function/Object-toSource.js b/js/src/tests/non262/Function/Object-toSource.js new file mode 100644 index 0000000000..16b2346fbf --- /dev/null +++ b/js/src/tests/non262/Function/Object-toSource.js @@ -0,0 +1,373 @@ +// |reftest| skip-if(!Object.prototype.toSource) + +var BUGNUMBER = 1317400; +var summary = "Function string representation in Object.prototype.toSource"; + +print(BUGNUMBER + ": " + summary); + +// Methods. + +assertEq(({ foo(){} }).toSource(), + "({foo(){}})"); +assertEq(({ *foo(){} }).toSource(), + "({*foo(){}})"); +assertEq(({ async foo(){} }).toSource(), + "({async foo(){}})"); + +assertEq(({ 1(){} }).toSource(), + "({1(){}})"); + +// Methods with more spacing. +// Spacing is kept. + +assertEq(({ foo (){} }).toSource(), + "({foo (){}})"); +assertEq(({ foo () {} }).toSource(), + "({foo () {}})"); + +// Methods with computed name. +// Method syntax is composed. + +let name = "foo"; +assertEq(({ [name](){} }).toSource(), + "({foo(){}})"); +assertEq(({ *[name](){} }).toSource(), + "({*foo(){}})"); +assertEq(({ async [name](){} }).toSource(), + "({async foo(){}})"); + +assertEq(({ [ Symbol.iterator ](){} }).toSource(), + "({[Symbol.iterator](){}})"); + +// Accessors. + +assertEq(({ get foo(){} }).toSource(), + "({get foo(){}})"); +assertEq(({ set foo(v){} }).toSource(), + "({set foo(v){}})"); + +// Accessors with computed name. +// Method syntax is composed. + +assertEq(({ get [name](){} }).toSource(), + "({get foo(){}})"); +assertEq(({ set [name](v){} }).toSource(), + "({set foo(v){}})"); + +assertEq(({ get [ Symbol.iterator ](){} }).toSource(), + "({get [Symbol.iterator](){}})"); +assertEq(({ set [ Symbol.iterator ](v){} }).toSource(), + "({set [Symbol.iterator](v){}})"); + +// Getter and setter with same name. +// Getter always comes before setter. + +assertEq(({ get foo(){}, set foo(v){} }).toSource(), + "({get foo(){}, set foo(v){}})"); +assertEq(({ set foo(v){}, get foo(){} }).toSource(), + "({get foo(){}, set foo(v){}})"); + +// Normal properties. + +assertEq(({ foo: function(){} }).toSource(), + "({foo:(function(){})})"); +assertEq(({ foo: function bar(){} }).toSource(), + "({foo:(function bar(){})})"); +assertEq(({ foo: function*(){} }).toSource(), + "({foo:(function*(){})})"); +assertEq(({ foo: async function(){} }).toSource(), + "({foo:(async function(){})})"); + +// Normal properties with computed name. + +assertEq(({ [ Symbol.iterator ]: function(){} }).toSource(), + "({[Symbol.iterator]:(function(){})})"); + +// Dynamically defined properties with function expression. +// Never become a method syntax. + +let obj = {}; +obj.foo = function() {}; +assertEq(obj.toSource(), + "({foo:(function() {})})"); + +obj = {}; +Object.defineProperty(obj, "foo", {value: function() {}}); +assertEq(obj.toSource(), + "({})"); + +obj = {}; +Object.defineProperty(obj, "foo", {value: function() {}, enumerable: true}); +assertEq(obj.toSource(), + "({foo:(function() {})})"); + +obj = {}; +Object.defineProperty(obj, "foo", {value: function bar() {}, enumerable: true}); +assertEq(obj.toSource(), + "({foo:(function bar() {})})"); + +obj = {}; +Object.defineProperty(obj, Symbol.iterator, {value: function() {}, enumerable: true}); +assertEq(obj.toSource(), + "({[Symbol.iterator]:(function() {})})"); + +// Dynamically defined property with other object's method. +// Method syntax is composed. + +let method = ({foo() {}}).foo; + +obj = {}; +Object.defineProperty(obj, "foo", {value: method, enumerable: true}); +assertEq(obj.toSource(), + "({foo() {}})"); + +obj = {}; +Object.defineProperty(obj, "bar", {value: method, enumerable: true}); +assertEq(obj.toSource(), + "({bar() {}})"); + +method = ({*foo() {}}).foo; + +obj = {}; +Object.defineProperty(obj, "bar", {value: method, enumerable: true}); +assertEq(obj.toSource(), + "({*bar() {}})"); + +method = ({async foo() {}}).foo; + +obj = {}; +Object.defineProperty(obj, "bar", {value: method, enumerable: true}); +assertEq(obj.toSource(), + "({async bar() {}})"); + +// Dynamically defined accessors. +// Accessor syntax is composed. + +obj = {}; +Object.defineProperty(obj, "foo", {get: function() {}, enumerable: true}); +assertEq(obj.toSource(), + "({get foo() {}})"); + +obj = {}; +Object.defineProperty(obj, "foo", {set: function() {}, enumerable: true}); +assertEq(obj.toSource(), + "({set foo() {}})"); + +obj = {}; +Object.defineProperty(obj, Symbol.iterator, {get: function() {}, enumerable: true}); +assertEq(obj.toSource(), + "({get [Symbol.iterator]() {}})"); + +obj = {}; +Object.defineProperty(obj, Symbol.iterator, {set: function() {}, enumerable: true}); +assertEq(obj.toSource(), + "({set [Symbol.iterator]() {}})"); + +// Dynamically defined accessors with other object's accessors. +// Accessor syntax is composed. + +let accessor = Object.getOwnPropertyDescriptor({ get foo() {} }, "foo").get; +obj = {}; +Object.defineProperty(obj, "foo", {get: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({get foo() {}})"); + +accessor = Object.getOwnPropertyDescriptor({ get bar() {} }, "bar").get; +obj = {}; +Object.defineProperty(obj, "foo", {get: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({get foo() {}})"); + +accessor = Object.getOwnPropertyDescriptor({ set foo(v) {} }, "foo").set; +obj = {}; +Object.defineProperty(obj, "foo", {get: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({get foo(v) {}})"); + +accessor = Object.getOwnPropertyDescriptor({ set bar(v) {} }, "bar").set; +obj = {}; +Object.defineProperty(obj, "foo", {get: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({get foo(v) {}})"); + +accessor = Object.getOwnPropertyDescriptor({ get foo() {} }, "foo").get; +obj = {}; +Object.defineProperty(obj, "foo", {set: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({set foo() {}})"); + +accessor = Object.getOwnPropertyDescriptor({ get bar() {} }, "bar").get; +obj = {}; +Object.defineProperty(obj, "foo", {set: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({set foo() {}})"); + +accessor = Object.getOwnPropertyDescriptor({ set foo(v) {} }, "foo").set; +obj = {}; +Object.defineProperty(obj, "foo", {set: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({set foo(v) {}})"); + +accessor = Object.getOwnPropertyDescriptor({ set bar(v) {} }, "bar").set; +obj = {}; +Object.defineProperty(obj, "foo", {set: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({set foo(v) {}})"); + +// Methods with proxy. +// Treated as normal property. + +method = ({foo() {}}).foo; +let handler = { + get(that, name) { + if (name == "toSource") { + return function() { + return that.toSource(); + }; + } + return that[name]; + } +}; +let proxy = new Proxy(method, handler); + +obj = {}; +Object.defineProperty(obj, "foo", {value: proxy, enumerable: true}); +assertEq(obj.toSource(), + "({foo:foo() {}})"); + +// Accessors with proxy. +// Accessor syntax is composed. + +accessor = Object.getOwnPropertyDescriptor({ get foo() {} }, "foo").get; +proxy = new Proxy(accessor, handler); + +obj = {}; +Object.defineProperty(obj, "foo", {get: proxy, enumerable: true}); +assertEq(obj.toSource(), + "({get foo() {}})"); + +obj = {}; +Object.defineProperty(obj, "foo", {set: proxy, enumerable: true}); +assertEq(obj.toSource(), + "({set foo() {}})"); + +// Methods from other global. +// Treated as normal property in the cross-compartment case. + +let g = newGlobal(); + +method = g.eval("({ foo() {} }).foo"); + +obj = {}; +Object.defineProperty(obj, "foo", {value: method, enumerable: true}); +assertEq((obj.toSource() === "({foo:foo() {}})" || + obj.toSource() === "({foo() {}})"), + true); + +// Accessors from other global. +// Accessor syntax is composed. + +accessor = g.eval("Object.getOwnPropertyDescriptor({ get foo() {} }, 'foo').get"); + +obj = {}; +Object.defineProperty(obj, "foo", {get: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({get foo() {}})"); + +accessor = g.eval("Object.getOwnPropertyDescriptor({ get bar() {} }, 'bar').get"); + +obj = {}; +Object.defineProperty(obj, "foo", {get: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({get foo() {}})"); + +accessor = g.eval("Object.getOwnPropertyDescriptor({ set foo(v) {} }, 'foo').set"); + +obj = {}; +Object.defineProperty(obj, "foo", {get: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({get foo(v) {}})"); + +accessor = g.eval("Object.getOwnPropertyDescriptor({ set bar(v) {} }, 'bar').set"); + +obj = {}; +Object.defineProperty(obj, "foo", {get: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({get foo(v) {}})"); + +accessor = g.eval("Object.getOwnPropertyDescriptor({ get foo() {} }, 'foo').get"); + +obj = {}; +Object.defineProperty(obj, "foo", {set: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({set foo() {}})"); + +accessor = g.eval("Object.getOwnPropertyDescriptor({ get bar() {} }, 'bar').get"); + +obj = {}; +Object.defineProperty(obj, "foo", {set: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({set foo() {}})"); + +accessor = g.eval("Object.getOwnPropertyDescriptor({ set foo(v) {} }, 'foo').set"); + +obj = {}; +Object.defineProperty(obj, "foo", {set: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({set foo(v) {}})"); + +accessor = g.eval("Object.getOwnPropertyDescriptor({ set bar(v) {} }, 'bar').set"); + +obj = {}; +Object.defineProperty(obj, "foo", {set: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({set foo(v) {}})"); + +// **** Some weird cases **** + +// Accessors with generator or async. + +obj = {}; +Object.defineProperty(obj, "foo", {get: function*() {}, enumerable: true}); +assertEq(obj.toSource(), + "({get foo() {}})"); + +obj = {}; +Object.defineProperty(obj, "foo", {set: async function() {}, enumerable: true}); +assertEq(obj.toSource(), + "({set foo() {}})"); + +// Modified toSource. + +obj = { foo() {} }; +obj.foo.toSource = () => "hello"; +assertEq(obj.toSource(), + "({hello})"); + +obj = { foo() {} }; +obj.foo.toSource = () => "bar() {}"; +assertEq(obj.toSource(), + "({bar() {}})"); + +// Modified toSource with different method name. + +obj = {}; +Object.defineProperty(obj, "foo", {value: function bar() {}, enumerable: true}); +obj.foo.toSource = () => "hello"; +assertEq(obj.toSource(), + "({foo:hello})"); + +obj = {}; +Object.defineProperty(obj, "foo", {value: function* bar() {}, enumerable: true}); +obj.foo.toSource = () => "hello"; +assertEq(obj.toSource(), + "({foo:hello})"); + +obj = {}; +Object.defineProperty(obj, "foo", {value: async function bar() {}, enumerable: true}); +obj.foo.toSource = () => "hello"; +assertEq(obj.toSource(), + "({foo:hello})"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Function/arguments-caller-callee.js b/js/src/tests/non262/Function/arguments-caller-callee.js new file mode 100644 index 0000000000..57efd9eb91 --- /dev/null +++ b/js/src/tests/non262/Function/arguments-caller-callee.js @@ -0,0 +1,64 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = 'arguments-caller-callee.js'; +var BUGNUMBER = 514563; +var summary = "arguments.caller and arguments.callee are poison pills in ES5, " + + "later changed in ES2017 to only poison pill arguments.callee."; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +// behavior + +function expectTypeError(fun) +{ + try + { + fun(); + throw new Error("didn't throw"); + } + catch (e) + { + assertEq(e instanceof TypeError, true, + "expected TypeError calling function" + + ("name" in fun ? " " + fun.name : "") + ", instead got: " + e); + } +} + +function bar() { "use strict"; return arguments; } +assertEq(bar().caller, undefined); // No error when accessing arguments.caller in ES2017+ +expectTypeError(function barCallee() { bar().callee; }); + +function baz() { return arguments; } +assertEq(baz().callee, baz); + + +// accessor identity + +function strictMode() { "use strict"; return arguments; } +var canonicalTTE = Object.getOwnPropertyDescriptor(strictMode(), "callee").get; + +var args = strictMode(); + +var argsCaller = Object.getOwnPropertyDescriptor(args, "caller"); +assertEq(argsCaller, undefined); + +var argsCallee = Object.getOwnPropertyDescriptor(args, "callee"); +assertEq("get" in argsCallee, true); +assertEq("set" in argsCallee, true); +assertEq(argsCallee.get, canonicalTTE); +assertEq(argsCallee.set, canonicalTTE); + + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Function/arguments-extra-property.js b/js/src/tests/non262/Function/arguments-extra-property.js new file mode 100644 index 0000000000..017734382d --- /dev/null +++ b/js/src/tests/non262/Function/arguments-extra-property.js @@ -0,0 +1,33 @@ +var BUGNUMBER = 1263811; +var summary = "GetElem for modified arguments shouldn't be optimized to get original argument."; + +print(BUGNUMBER + ": " + summary); + +function testModifyFirst() { + function f() { + Object.defineProperty(arguments, 1, { value: 30 }); + assertEq(arguments[1], 30); + } + for (let i = 0; i < 10; i++) + f(10, 20); +} +testModifyFirst(); + +function testModifyLater() { + function f() { + var ans = 20; + for (let i = 0; i < 10; i++) { + if (i == 5) { + Object.defineProperty(arguments, 1, { value: 30 }); + ans = 30; + } + assertEq(arguments[1], ans); + } + } + for (let i = 0; i < 10; i++) + f(10, 20); +} +testModifyLater(); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Function/arguments-iterator.js b/js/src/tests/non262/Function/arguments-iterator.js new file mode 100644 index 0000000000..5610b8a245 --- /dev/null +++ b/js/src/tests/non262/Function/arguments-iterator.js @@ -0,0 +1,167 @@ +var BUGNUMBER = 992617; +var summary = "Implement arguments[@@iterator]."; + +print(BUGNUMBER + ": " + summary); + +// MappedArgumentsObject +let mapped = [ + function(a, b, c) { + assertEq(Symbol.iterator in arguments, true); + delete arguments[Symbol.iterator]; + assertEq(Symbol.iterator in arguments, false); + }, + function(a, b, c) { + delete arguments[Symbol.iterator]; + assertEq(Symbol.iterator in arguments, false); + }, + function(a, b, c) { + arguments[Symbol.iterator] = 10; + delete arguments[Symbol.iterator]; + assertEq(Symbol.iterator in arguments, false); + }, + function(a, b, c) { + Object.defineProperty(arguments, Symbol.iterator, { + value: 10, writable: true, enumerable: true, configurable: true + }); + delete arguments[Symbol.iterator]; + assertEq(Symbol.iterator in arguments, false); + }, + function(a, b, c) { + assertEq(arguments[Symbol.iterator], Array.prototype[Symbol.iterator]); + }, + function(a, b, c) { + assertEq(arguments[Symbol.iterator].name, "values"); + }, + function(a, b, c) { + var desc = Object.getOwnPropertyDescriptor(arguments, Symbol.iterator); + assertEq("value" in desc, true); + assertEq(desc.value, Array.prototype[Symbol.iterator]); + assertEq(desc.writable, true); + assertEq(desc.enumerable, false); + assertEq(desc.configurable, true); + }, + function(a, b, c) { + var iter = arguments[Symbol.iterator](); + assertDeepEq(iter.next(), { value: 10, done: false }); + assertDeepEq(iter.next(), { value: 20, done: false }); + assertDeepEq(iter.next(), { value: 30, done: false }); + assertDeepEq(iter.next(), { value: undefined, done: true }); + }, + function(a, b, c) { + assertDeepEq([...arguments], [10, 20, 30]); + }, + function(a, b, c) { + b = 40; + assertDeepEq([...arguments], [10, 40, 30]); + }, + function(a, b, c) { + arguments.length = 4; + assertDeepEq([...arguments], [10, 20, 30, undefined]); + }, + function(a, b, c) { + arguments[5] = 50; + assertDeepEq([...arguments], [10, 20, 30]); + }, + function(a, b, c) { + arguments[Symbol.iterator] = function*() { + yield 40; + yield 50; + yield 60; + }; + assertDeepEq([...arguments], [40, 50, 60]); + }, +]; +for (let f of mapped) { + f(10, 20, 30); +} + +var g1 = newGlobal(); +assertEq(g1.eval(` +function f(a, b, c) { + return arguments[Symbol.iterator].name; +} +f(1, 2, 3); +`), "values"); + +// UnmappedArgumentsObject +let unmapped = [ + function([a], b, c) { + assertEq(Symbol.iterator in arguments, true); + delete arguments[Symbol.iterator]; + assertEq(Symbol.iterator in arguments, false); + }, + function([a], b, c) { + delete arguments[Symbol.iterator]; + assertEq(Symbol.iterator in arguments, false); + }, + function([a], b, c) { + arguments[Symbol.iterator] = 10; + delete arguments[Symbol.iterator]; + assertEq(Symbol.iterator in arguments, false); + }, + function([a], b, c) { + Object.defineProperty(arguments, Symbol.iterator, { + value: 10, writable: true, enumerable: true, configurable: true + }); + delete arguments[Symbol.iterator]; + assertEq(Symbol.iterator in arguments, false); + }, + function([a], b, c) { + assertEq(arguments[Symbol.iterator], Array.prototype[Symbol.iterator]); + }, + function([a], b, c) { + assertEq(arguments[Symbol.iterator].name, "values"); + }, + function([a], b, c) { + var desc = Object.getOwnPropertyDescriptor(arguments, Symbol.iterator); + assertEq("value" in desc, true); + assertEq(desc.value, Array.prototype[Symbol.iterator]); + assertEq(desc.writable, true); + assertEq(desc.enumerable, false); + assertEq(desc.configurable, true); + }, + function([a], b, c) { + var iter = arguments[Symbol.iterator](); + assertDeepEq(iter.next(), { value: [10], done: false }); + assertDeepEq(iter.next(), { value: 20, done: false }); + assertDeepEq(iter.next(), { value: 30, done: false }); + assertDeepEq(iter.next(), { value: undefined, done: true }); + }, + function([a], b, c) { + assertDeepEq([...arguments], [[10], 20, 30]); + }, + function([a], b, c) { + b = 40; + assertDeepEq([...arguments], [[10], 20, 30]); + }, + function([a], b, c) { + arguments.length = 4; + assertDeepEq([...arguments], [[10], 20, 30, undefined]); + }, + function([a], b, c) { + arguments[5] = 50; + assertDeepEq([...arguments], [[10], 20, 30]); + }, + function([a], b, c) { + arguments[Symbol.iterator] = function*() { + yield 40; + yield 50; + yield 60; + }; + assertDeepEq([...arguments], [40, 50, 60]); + }, +]; +for (let f of unmapped) { + f([10], 20, 30); +} + +var g2 = newGlobal(); +assertEq(g2.eval(` +function f([a], b, c) { + return arguments[Symbol.iterator].name; +} +f([1], 2, 3); +`), "values"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Function/arguments-parameter-shadowing.js b/js/src/tests/non262/Function/arguments-parameter-shadowing.js new file mode 100644 index 0000000000..bc2b430112 --- /dev/null +++ b/js/src/tests/non262/Function/arguments-parameter-shadowing.js @@ -0,0 +1,22 @@ +// Test that var declarations of arguments "shadows" the arguments binding +// used in parameter expressions. + +function g8(h = () => arguments) { + var arguments = 0; + assertEq(arguments, 0); + assertEq(arguments === h(), false); +} +g8(); + +function g9(h = () => arguments) { + var arguments; + assertEq(void 0 === arguments, false); + assertEq(h(), arguments); + arguments = 0; + assertEq(arguments, 0); + assertEq(arguments === h(), false); +} +g9(); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Function/arguments-property-attributes.js b/js/src/tests/non262/Function/arguments-property-attributes.js new file mode 100644 index 0000000000..f50c1e6dad --- /dev/null +++ b/js/src/tests/non262/Function/arguments-property-attributes.js @@ -0,0 +1,98 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = 'arguments-property-attributes.js'; +var BUGNUMBER = 516255; +var summary = "Attributes for properties of arguments objects"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +// normal + +function args() { return arguments; } +var a = args(0, 1); + +var argProps = Object.getOwnPropertyNames(a).sort(); +assertEq(argProps.indexOf("callee") >= 0, true); +assertEq(argProps.indexOf("0") >= 0, true); +assertEq(argProps.indexOf("1") >= 0, true); +assertEq(argProps.indexOf("length") >= 0, true); + +var calleeDesc = Object.getOwnPropertyDescriptor(a, "callee"); +assertEq(calleeDesc.value, args); +assertEq(calleeDesc.writable, true); +assertEq(calleeDesc.enumerable, false); +assertEq(calleeDesc.configurable, true); + +var zeroDesc = Object.getOwnPropertyDescriptor(a, "0"); +assertEq(zeroDesc.value, 0); +assertEq(zeroDesc.writable, true); +assertEq(zeroDesc.enumerable, true); +assertEq(zeroDesc.configurable, true); + +var oneDesc = Object.getOwnPropertyDescriptor(a, "1"); +assertEq(oneDesc.value, 1); +assertEq(oneDesc.writable, true); +assertEq(oneDesc.enumerable, true); +assertEq(oneDesc.configurable, true); + +var lengthDesc = Object.getOwnPropertyDescriptor(a, "length"); +assertEq(lengthDesc.value, 2); +assertEq(lengthDesc.writable, true); +assertEq(lengthDesc.enumerable, false); +assertEq(lengthDesc.configurable, true); + + +// strict + +function strictArgs() { "use strict"; return arguments; } +var sa = strictArgs(0, 1); + +var strictArgProps = Object.getOwnPropertyNames(sa).sort(); +assertEq(strictArgProps.indexOf("callee") >= 0, true); +assertEq(strictArgProps.indexOf("caller") >= 0, false); +assertEq(strictArgProps.indexOf("0") >= 0, true); +assertEq(strictArgProps.indexOf("1") >= 0, true); +assertEq(strictArgProps.indexOf("length") >= 0, true); + +var strictCalleeDesc = Object.getOwnPropertyDescriptor(sa, "callee"); +assertEq(typeof strictCalleeDesc.get, "function"); +assertEq(typeof strictCalleeDesc.set, "function"); +assertEq(strictCalleeDesc.get, strictCalleeDesc.set); +assertEq(strictCalleeDesc.enumerable, false); +assertEq(strictCalleeDesc.configurable, false); + +var strictCallerDesc = Object.getOwnPropertyDescriptor(sa, "caller"); +assertEq(strictCallerDesc, undefined); + +var strictZeroDesc = Object.getOwnPropertyDescriptor(sa, "0"); +assertEq(strictZeroDesc.value, 0); +assertEq(strictZeroDesc.writable, true); +assertEq(strictZeroDesc.enumerable, true); +assertEq(strictZeroDesc.configurable, true); + +var strictOneDesc = Object.getOwnPropertyDescriptor(sa, "1"); +assertEq(strictOneDesc.value, 1); +assertEq(strictOneDesc.writable, true); +assertEq(strictOneDesc.enumerable, true); +assertEq(strictOneDesc.configurable, true); + +var strictLengthDesc = Object.getOwnPropertyDescriptor(sa, "length"); +assertEq(strictLengthDesc.value, 2); +assertEq(strictLengthDesc.writable, true); +assertEq(strictLengthDesc.enumerable, false); +assertEq(strictLengthDesc.configurable, true); + + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Function/arrow-has-duplicated.js b/js/src/tests/non262/Function/arrow-has-duplicated.js new file mode 100644 index 0000000000..19096ebf88 --- /dev/null +++ b/js/src/tests/non262/Function/arrow-has-duplicated.js @@ -0,0 +1,15 @@ +// Make sure duplicated name is allowed in non-strict. +function f0(a, a) { +} + +// SyntaxError should be thrown if arrow function has duplicated name. +assertThrowsInstanceOf(() => eval(` +(a, a) => { +}; +`), SyntaxError); +assertThrowsInstanceOf(() => eval(` +(a, ...a) => { +}; +`), SyntaxError); + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Function/bound-length-and-name.js b/js/src/tests/non262/Function/bound-length-and-name.js new file mode 100644 index 0000000000..ef2f1ffbcd --- /dev/null +++ b/js/src/tests/non262/Function/bound-length-and-name.js @@ -0,0 +1,40 @@ +var proxy = new Proxy(function() {}, { + getOwnPropertyDescriptor(target, name) { + assertEq(name, "length"); + return {value: 3, configurable: true}; + }, + + get(target, name) { + if (name == "length") + return 3; + if (name == "name") + return "hello world"; + assertEq(false, true); + } +}) + +var bound = Function.prototype.bind.call(proxy); +assertEq(bound.name, "bound hello world"); +assertEq(bound.length, 3); + +var fun = function() {}; +Object.defineProperty(fun, "name", {value: 1337}); +Object.defineProperty(fun, "length", {value: "15"}); +bound = fun.bind(); +assertEq(bound.name, "bound "); +assertEq(bound.length, 0); + +Object.defineProperty(fun, "length", {value: Number.MAX_SAFE_INTEGER}); +bound = fun.bind(); +assertEq(bound.length, Number.MAX_SAFE_INTEGER); + +Object.defineProperty(fun, "length", {value: -100}); +bound = fun.bind(); +assertEq(bound.length, 0); + +fun = function f(a, ...b) { }; +assertEq(fun.length, 1); +bound = fun.bind(); +assertEq(bound.length, 1); + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Function/bound-non-constructable.js b/js/src/tests/non262/Function/bound-non-constructable.js new file mode 100644 index 0000000000..cee1dd580d --- /dev/null +++ b/js/src/tests/non262/Function/bound-non-constructable.js @@ -0,0 +1,17 @@ +var objects = [ + Math.sin.bind(null), + new Proxy(Math.sin.bind(null), {}), + Function.prototype.bind.call(new Proxy(Math.sin, {})) +] + +for (var obj of objects) { + // Target is not constructable, so a new array should be created internally. + assertDeepEq(Array.from.call(obj, [1, 2, 3]), [1, 2, 3]); + assertDeepEq(Array.of.call(obj, 1, 2, 3), [1, 2, 3]); + + // Make sure they are callable, but not constructable. + obj(); + assertThrowsInstanceOf(() => new obj, TypeError); +} + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Function/bound-prototype.js b/js/src/tests/non262/Function/bound-prototype.js new file mode 100644 index 0000000000..8b0f295a58 --- /dev/null +++ b/js/src/tests/non262/Function/bound-prototype.js @@ -0,0 +1,37 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +function Bound(fn) { + return Function.prototype.bind.call(fn); +} + +var fnDefaultPrototype = function(){}; +assertEq(Object.getPrototypeOf(Bound(fnDefaultPrototype)), Function.prototype); + +var fnGeneratorPrototype = function*(){}; +assertEq(Object.getPrototypeOf(Bound(fnGeneratorPrototype)), function*(){}.constructor.prototype); + +var fnCustomPrototype = Object.setPrototypeOf(function(){}, Array.prototype); +assertEq(Object.getPrototypeOf(Bound(fnCustomPrototype)), Array.prototype); + +var fnNullPrototype = Object.setPrototypeOf(function(){}, null); +assertEq(Object.getPrototypeOf(Bound(fnNullPrototype)), null); + + +function LoggingProxy(target) { + var log = []; + var proxy = new Proxy(target, new Proxy({}, { + get(target, propertyKey, receiver) { + log.push(propertyKey); + } + })); + return {proxy, log}; +} + +var {proxy, log} = LoggingProxy(function(){}); +Bound(proxy); +assertEqArray(log, ["getPrototypeOf", "getOwnPropertyDescriptor", "get", "get"]); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Function/browser.js b/js/src/tests/non262/Function/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Function/builtin-no-construct.js b/js/src/tests/non262/Function/builtin-no-construct.js new file mode 100644 index 0000000000..b41ae56f11 --- /dev/null +++ b/js/src/tests/non262/Function/builtin-no-construct.js @@ -0,0 +1,52 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +function checkMethod(method) { + try { + new method(); + assertEq(0, 1, "not reached " + method); + } catch (e) { + assertEq(e.message.indexOf(" is not a constructor") === -1, false); + } +} + +function checkMethods(proto) { + var names = Object.getOwnPropertyNames(proto); + for (var i = 0; i < names.length; i++) { + var name = names[i]; + if (["constructor", "arguments", "caller"].indexOf(name) >= 0) + continue; + var prop = proto[name]; + if (typeof prop === "function") + checkMethod(prop); + } +} + +checkMethod(Function.prototype); +checkMethods(JSON); +checkMethods(Math); +checkMethods(Proxy); + +var builtin_ctors = [ + Object, Function, Array, String, Boolean, Number, Date, RegExp, Error, + EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError, +]; + +for (var i = 0; i < builtin_ctors.length; i++) { + checkMethods(builtin_ctors[i]); + checkMethods(builtin_ctors[i].prototype); +} + +var builtin_funcs = [ + eval, isFinite, isNaN, parseFloat, parseInt, + decodeURI, decodeURIComponent, encodeURI, encodeURIComponent +]; + +for (var i = 0; i < builtin_funcs.length; i++) { + checkMethod(builtin_funcs[i]); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Function/builtin-no-prototype.js b/js/src/tests/non262/Function/builtin-no-prototype.js new file mode 100644 index 0000000000..b5a8cc9f6e --- /dev/null +++ b/js/src/tests/non262/Function/builtin-no-prototype.js @@ -0,0 +1,40 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- */ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +assertEq(undefined, void 0); + +assertEq(Function.prototype.hasOwnProperty('prototype'), false); +assertEq(Function.prototype.prototype, undefined); + +var builtin_ctors = [ + Object, Function, Array, String, Boolean, Number, Date, RegExp, Error, + EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError +]; + +for (var i = 0; i < builtin_ctors.length; i++) { + var c = builtin_ctors[i]; + assertEq(typeof c.prototype, (c === Function) ? "function" : "object"); + assertEq(c.prototype.constructor, c); +} + +var builtin_funcs = [ + eval, isFinite, isNaN, parseFloat, parseInt, + decodeURI, decodeURIComponent, encodeURI, encodeURIComponent +]; + +for (var i = 0; i < builtin_funcs.length; i++) { + assertEq(builtin_funcs[i].hasOwnProperty('prototype'), false); + assertEq(builtin_funcs[i].prototype, undefined); +} + +var names = Object.getOwnPropertyNames(Math); +for (var i = 0; i < names.length; i++) { + var m = Math[names[i]]; + if (typeof m === "function") + assertEq(m.prototype, undefined); +} + +reportCompare(0, 0, "don't crash"); diff --git a/js/src/tests/non262/Function/configurable-length-builtins.js b/js/src/tests/non262/Function/configurable-length-builtins.js new file mode 100644 index 0000000000..f28eaae157 --- /dev/null +++ b/js/src/tests/non262/Function/configurable-length-builtins.js @@ -0,0 +1,21 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Deleting .length from a variety of builtin functions works as expected. +for (var fun of [Math.sin, Array.prototype.map, eval]) { + assertEq(delete fun.length, true); + assertEq(fun.hasOwnProperty("length"), false); + assertEq("length" in fun, true); // still inheriting Function.prototype.length + assertEq(fun.length, 0); + + // The inherited property is nonwritable, so assigning still fails + // (silently, in sloppy mode). + fun.length = Math.hypot; + assertEq(fun.length, 0); + + // It can be shadowed via defineProperty. + Object.defineProperty(fun, "length", {value: Math.hypot}); + assertEq(fun.length, Math.hypot); +} + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Function/configurable-length.js b/js/src/tests/non262/Function/configurable-length.js new file mode 100644 index 0000000000..127038fb56 --- /dev/null +++ b/js/src/tests/non262/Function/configurable-length.js @@ -0,0 +1,86 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Very simple initial test that the "length" property of a function is +// configurable. More thorough tests follow. +var f = function (a1, a2, a3, a4) {}; +assertEq(delete f.length, true); +assertEq(f.hasOwnProperty("length"), false); +assertEq(f.length, 0); // inherited from Function.prototype.length +assertEq(delete Function.prototype.length, true); +assertEq(f.length, undefined); + + +// Now for the details. +// +// Many of these tests are poking at the "resolve hook" mechanism SM uses to +// lazily create this property, which is wonky and deserving of some extra +// skepticism. + +// We've deleted Function.prototype.length. Check that the resolve hook does +// not resurrect it. +assertEq("length" in Function.prototype, false); +Function.prototype.length = 7; +assertEq(Function.prototype.length, 7); +delete Function.prototype.length; +assertEq(Function.prototype.length, undefined); + +// OK, define Function.prototype.length back to its original state per spec, so +// the remaining tests can run in a more typical environment. +Object.defineProperty(Function.prototype, "length", {value: 0, configurable: true}); + +// Check the property descriptor of a function length property. +var g = function f(a1, a2, a3, a4, a5) {}; +var desc = Object.getOwnPropertyDescriptor(g, "length"); +assertEq(desc.configurable, true); +assertEq(desc.enumerable, false); +assertEq(desc.writable, false); +assertEq(desc.value, 5); + +// After deleting the length property, assigning to f.length fails because +// Function.prototype.length is non-writable. In strict mode it would throw. +delete g.length; +g.length = 12; +assertEq(g.hasOwnProperty("length"), false); +assertEq(g.length, 0); + +// After deleting both the length property and Function.prototype.length, +// assigning to f.length creates a new plain old data property. +delete Function.prototype.length; +g.length = 13; +var desc = Object.getOwnPropertyDescriptor(g, "length"); +assertEq(desc.configurable, true); +assertEq(desc.enumerable, true); +assertEq(desc.writable, true); +assertEq(desc.value, 13); + +// Deleting the .length of one instance of a FunctionDeclaration does not +// affect other instances. +function mkfun() { + function fun(a1, a2, a3, a4, a5) {} + return fun; +} +g = mkfun(); +var h = mkfun(); +delete h.length; +assertEq(g.length, 5); +assertEq(mkfun().length, 5); + +// Object.defineProperty on a brand-new function is sufficient to cause the +// LENGTH_RESOLVED flag to be set. +g = mkfun(); +Object.defineProperty(g, "length", {value: 0}); +assertEq(delete g.length, true); +assertEq(g.hasOwnProperty("length"), false); + +// Object.defineProperty on a brand-new function correctly merges new +// attributes with the builtin ones. +g = mkfun(); +Object.defineProperty(g, "length", { value: 42 }); +desc = Object.getOwnPropertyDescriptor(g, "length"); +assertEq(desc.configurable, true); +assertEq(desc.enumerable, false); +assertEq(desc.writable, false); +assertEq(desc.value, 42); + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Function/construct-bound-proxy-with-many-arguments.js b/js/src/tests/non262/Function/construct-bound-proxy-with-many-arguments.js new file mode 100644 index 0000000000..6c9bb41a38 --- /dev/null +++ b/js/src/tests/non262/Function/construct-bound-proxy-with-many-arguments.js @@ -0,0 +1,13 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var proxy = Function.prototype.bind.call(new Proxy(Array, {})); +for (var i = 10; i < 50; ++i) { + var args = Array(i).fill(i); + var array = new proxy(...args); + assertEqArray(array, args); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Function/constructor-binding.js b/js/src/tests/non262/Function/constructor-binding.js new file mode 100644 index 0000000000..e82274d279 --- /dev/null +++ b/js/src/tests/non262/Function/constructor-binding.js @@ -0,0 +1,11 @@ +var BUGNUMBER = 636635; +var summary = "A function created by Function constructor shouldn't have anonymous binding"; + +print(BUGNUMBER + ": " + summary); + +assertEq(new Function("return typeof anonymous")(), "undefined"); +assertEq(new Function("return function() { return typeof anonymous; }")()(), "undefined"); +assertEq(new Function("return function() { eval(''); return typeof anonymous; }")()(), "undefined"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Function/create-function-parse-before-getprototype.js b/js/src/tests/non262/Function/create-function-parse-before-getprototype.js new file mode 100644 index 0000000000..2095abfb28 --- /dev/null +++ b/js/src/tests/non262/Function/create-function-parse-before-getprototype.js @@ -0,0 +1,17 @@ +var getProtoCalled = false; + +var newTarget = Object.defineProperty(function(){}.bind(), "prototype", { + get() { + getProtoCalled = true; + return null; + } +}); + +assertThrowsInstanceOf(() => { + Reflect.construct(Function, ["@error"], newTarget); +}, SyntaxError); + +assertEq(getProtoCalled, false); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Function/function-bind.js b/js/src/tests/non262/Function/function-bind.js new file mode 100644 index 0000000000..9fdaf41a97 --- /dev/null +++ b/js/src/tests/non262/Function/function-bind.js @@ -0,0 +1,280 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = 'function-bind.js'; +var BUGNUMBER = 429507; +var summary = "ES5: Function.prototype.bind"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +// ad-hoc testing + +assertEq(Function.prototype.hasOwnProperty("bind"), true); + +var bind = Function.prototype.bind; +assertEq(bind.length, 1); + + +var strictReturnThis = function() { "use strict"; return this; }; + +assertEq(strictReturnThis.bind(undefined)(), undefined); +assertEq(strictReturnThis.bind(null)(), null); + +var obj = {}; +assertEq(strictReturnThis.bind(obj)(), obj); + +assertEq(strictReturnThis.bind(NaN)(), NaN); + +assertEq(strictReturnThis.bind(true)(), true); +assertEq(strictReturnThis.bind(false)(), false); + +assertEq(strictReturnThis.bind("foopy")(), "foopy"); + + +// rigorous, step-by-step testing + +function expectThrowTypeError(fun) +{ + try + { + var r = fun(); + throw new Error("didn't throw TypeError, returned " + r); + } + catch (e) + { + assertEq(e instanceof TypeError, true, + "didn't throw TypeError, got: " + e); + } +} + +/* + * 1. Let Target be the this value. + * 2. If IsCallable(Target) is false, throw a TypeError exception. + */ +expectThrowTypeError(function() { bind.call(null); }); +expectThrowTypeError(function() { bind.call(undefined); }); +expectThrowTypeError(function() { bind.call(NaN); }); +expectThrowTypeError(function() { bind.call(0); }); +expectThrowTypeError(function() { bind.call(-0); }); +expectThrowTypeError(function() { bind.call(17); }); +expectThrowTypeError(function() { bind.call(42); }); +expectThrowTypeError(function() { bind.call("foobar"); }); +expectThrowTypeError(function() { bind.call(true); }); +expectThrowTypeError(function() { bind.call(false); }); +expectThrowTypeError(function() { bind.call([]); }); +expectThrowTypeError(function() { bind.call({}); }); + + +/* + * 3. Let A be a new (possibly empty) internal list of all of the argument + * values provided after thisArg (arg1, arg2 etc), in order. + * 4. Let F be a new native ECMAScript object . + * 5. Set all the internal methods, except for [[Get]], of F as specified in + * 8.12. + * 6. Set the [[Get]] internal property of F as specified in 15.3.5.4. + * 7. Set the [[TargetFunction]] internal property of F to Target. + * 8. Set the [[BoundThis]] internal property of F to the value of thisArg. + * 9. Set the [[BoundArgs]] internal property of F to A. + */ +// throughout + + +/* 10. Set the [[Class]] internal property of F to "Function". */ +var toString = Object.prototype.toString; +assertEq(toString.call(function(){}), "[object Function]"); +assertEq(toString.call(function a(){}), "[object Function]"); +assertEq(toString.call(function(a){}), "[object Function]"); +assertEq(toString.call(function a(b){}), "[object Function]"); +assertEq(toString.call(function(){}.bind()), "[object Function]"); +assertEq(toString.call(function a(){}.bind()), "[object Function]"); +assertEq(toString.call(function(a){}.bind()), "[object Function]"); +assertEq(toString.call(function a(b){}.bind()), "[object Function]"); + + +/* + * 11. Set the [[Prototype]] internal property of F to the standard built-in + * Function prototype object as specified in 15.3.3.1. + */ +assertEq(Object.getPrototypeOf(bind.call(function(){})), Function.prototype); +assertEq(Object.getPrototypeOf(bind.call(function a(){})), Function.prototype); +assertEq(Object.getPrototypeOf(bind.call(function(a){})), Function.prototype); +assertEq(Object.getPrototypeOf(bind.call(function a(b){})), Function.prototype); + + +/* + * 12. Set the [[Call]] internal property of F as described in 15.3.4.5.1. + */ +var a = Array.bind(1, 2); +assertEq(a().length, 2); +assertEq(a(4).length, 2); +assertEq(a(4, 8).length, 3); + +function t() { return this; } +var bt = t.bind(t); +assertEq(bt(), t); + +function callee() { return arguments.callee; } +var call = callee.bind(); +assertEq(call(), callee); +assertEq(new call(), callee); + + +/* + * 13. Set the [[Construct]] internal property of F as described in 15.3.4.5.2. + */ +function Point(x, y) +{ + this.x = x; + this.y = y; +} +var YAxisPoint = Point.bind(null, 0) + +assertEq(YAxisPoint.hasOwnProperty("prototype"), false); +var p = new YAxisPoint(5); +assertEq(p.x, 0); +assertEq(p.y, 5); +assertEq(p instanceof Point, true); +assertEq(p instanceof YAxisPoint, true); +assertEq(Object.prototype.toString.call(YAxisPoint), "[object Function]"); +assertEq(YAxisPoint.length, 1); + + +/* + * 14. Set the [[HasInstance]] internal property of F as described in + * 15.3.4.5.3. + */ +function JoinArguments() +{ + this.args = Array.prototype.join.call(arguments, ", "); +} + +var Join1 = JoinArguments.bind(null, 1); +var Join2 = Join1.bind(null, 2); +var Join3 = Join2.bind(null, 3); +var Join4 = Join3.bind(null, 4); +var Join5 = Join4.bind(null, 5); +var Join6 = Join5.bind(null, 6); + +var r = new Join6(7); +assertEq(r instanceof Join6, true); +assertEq(r instanceof Join5, true); +assertEq(r instanceof Join4, true); +assertEq(r instanceof Join3, true); +assertEq(r instanceof Join2, true); +assertEq(r instanceof Join1, true); +assertEq(r instanceof JoinArguments, true); +assertEq(r.args, "1, 2, 3, 4, 5, 6, 7"); + + +/* + * 15. If the [[Class]] internal property of Target is "Function", then + * a. Let L be the length property of Target minus the length of A. + * b. Set the length own property of F to either 0 or L, whichever is larger. + * 16. Else set the length own property of F to 0. + */ +function none() { return arguments.length; } +assertEq(none.bind(1, 2)(3, 4), 3); +assertEq(none.bind(1, 2)(), 1); +assertEq(none.bind(1)(2, 3), 2); +assertEq(none.bind().length, 0); +assertEq(none.bind(null).length, 0); +assertEq(none.bind(null, 1).length, 0); +assertEq(none.bind(null, 1, 2).length, 0); + +function one(a) { } +assertEq(one.bind().length, 1); +assertEq(one.bind(null).length, 1); +assertEq(one.bind(null, 1).length, 0); +assertEq(one.bind(null, 1, 2).length, 0); + +// retch +var br = Object.create(null, { length: { value: 0 } }); +try +{ + br = bind.call(/a/g, /a/g, "aaaa"); +} +catch (e) { /* nothing */ } +assertEq(br.length, 0); + + +/* + * 17. Set the attributes of the length own property of F to the values + * specified in 15.3.5.1. + */ +var len1Desc = + Object.getOwnPropertyDescriptor(function(a, b, c){}.bind(), "length"); +assertEq(len1Desc.value, 3); +assertEq(len1Desc.writable, false); +assertEq(len1Desc.enumerable, false); +assertEq(len1Desc.configurable, true); + +var len2Desc = + Object.getOwnPropertyDescriptor(function(a, b, c){}.bind(null, 2), "length"); +assertEq(len2Desc.value, 2); +assertEq(len2Desc.writable, false); +assertEq(len2Desc.enumerable, false); +assertEq(len2Desc.configurable, true); + + +/* + * 18. Set the [[Extensible]] internal property of F to true. + */ +var bound = (function() { }).bind(); + +var isExtensible = Object.isExtensible || function() { return true; }; +assertEq(isExtensible(bound), true); + +bound.foo = 17; +var fooDesc = Object.getOwnPropertyDescriptor(bound, "foo"); +assertEq(fooDesc.value, 17); +assertEq(fooDesc.writable, true); +assertEq(fooDesc.enumerable, true); +assertEq(fooDesc.configurable, true); + + +/* + * Steps 19-21 are removed from ES6, instead implemented through "arguments" and + * "caller" accessors on Function.prototype. So no own properties, but do check + * for the same observable behavior (modulo where the accessors live). + */ +function strict() { "use strict"; } +function nonstrict() {} + +function testBound(fun) +{ + var boundf = fun.bind(); + + assertEq(Object.getOwnPropertyDescriptor(boundf, "arguments"), undefined, + "should be no arguments property"); + assertEq(Object.getOwnPropertyDescriptor(boundf, "caller"), undefined, + "should be no caller property"); + + expectThrowTypeError(function() { return boundf.arguments; }); + expectThrowTypeError(function() { return boundf.caller; }); +} + +testBound(strict); +testBound(nonstrict); + +assertEq((function unbound(){"body"}).bind().toString(), `function() { + [native code] +}`); + + +/* 22. Return F. */ +var passim = function p(){}.bind(1); +assertEq(typeof passim, "function"); + + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Function/function-call.js b/js/src/tests/non262/Function/function-call.js new file mode 100644 index 0000000000..756b583842 --- /dev/null +++ b/js/src/tests/non262/Function/function-call.js @@ -0,0 +1,134 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: + * Jeff Walden + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 575535; +var summary = 'Function.prototype.call'; +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function expectTypeError(fun, msg) +{ + try + { + fun(); + assertEq(true, false, "should have thrown a TypeError"); + } + catch (e) + { + assertEq(e instanceof TypeError, true, msg + "; instead threw " + e); + } +} + +function fun() { } + +var global = this; + +assertEq(Function.prototype.call.length, 1); + + +/* Step 1. */ +var nonfuns = [null, 1, -1, 2.5, "[[Call]]", undefined, true, false, {}]; +for (var i = 0, sz = nonfuns.length; i < sz; i++) +{ + var f = function() + { + Function.prototype.call.apply(nonfuns[i]); + }; + var msg = + "expected TypeError calling Function.prototype.call with uncallable this"; + expectTypeError(f, msg); +} + + +/* Steps 2-4. */ +function none() +{ + assertEq(this, global, "bad this"); + assertEq(arguments.length, 0, "wrong arguments"); +} + +none.call(); +none.call(undefined); +none.call(null); + +var seenThis; +function strictNone() +{ + "use strict"; + assertEq(this, seenThis, "bad this"); + assertEq(arguments.length, 0, "wrong arguments"); +} + +seenThis = undefined; +strictNone.call(); +strictNone.call(undefined); + +seenThis = null; +strictNone.call(null); + +seenThis = 17; +strictNone.call(17); + +var seenThisBox, args; +function some() +{ + assertEq(this instanceof seenThisBox, true, + "this not instanceof " + seenThisBox); + assertEq(this.valueOf(), seenThis, + "wrong this valueOf()"); + assertEq(arguments.length, args.length, "wrong arguments count"); + for (var i = 0; i < args.length; i++) + assertEq(arguments[i], args[i], "wrong argument " + i); +} + +seenThis = false; +seenThisBox = Boolean; +args = [8, 6, 7, NaN, undefined, 0.3]; +some.call(false, 8, 6, 7, NaN, undefined, 0.3); + +var obj = {}; + +seenThis = "foo"; +seenThisBox = String; +args = [obj]; +some.call("foo", obj); + +seenThis = obj; +seenThisBox = Object; +some.call(obj, obj); + +function strictSome() +{ + "use strict"; + assertEq(this, seenThis, "wrong this"); + assertEq(arguments.length, args.length, "wrong arguments count"); + for (var i = 0; i < args.length; i++) + assertEq(arguments[i], args[i], "wrong argument " + i); +} + +seenThis = NaN; +args = [8, 6, 7, NaN, undefined, 0.3]; +strictSome.call(NaN, 8, 6, 7, NaN, undefined, 0.3); + +seenThis = "foo"; +args = [obj]; +strictSome.call("foo", obj); + +seenThis = obj; +strictSome.call(obj, obj); + + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Function/function-caller-restrictions.js b/js/src/tests/non262/Function/function-caller-restrictions.js new file mode 100644 index 0000000000..36c31279ba --- /dev/null +++ b/js/src/tests/non262/Function/function-caller-restrictions.js @@ -0,0 +1,29 @@ +// Function#caller restrictions as proposed by +// https://github.com/claudepache/es-legacy-function-reflection/ + +function caller() { + return caller.caller; +} + +assertEq(caller(), null); +assertEq(Reflect.apply(caller, undefined, []), null); + +assertEq([0].map(caller)[0], null); + +(function strict() { + "use strict"; + assertEq(caller(), null); +})(); + +(async function() { + assertEq(caller(), null); +})(); + +assertEq(function*() { + yield caller(); +}().next().value, null); + + +if (typeof reportCompare === "function") { + reportCompare(true, true); +} diff --git a/js/src/tests/non262/Function/function-caller.js b/js/src/tests/non262/Function/function-caller.js new file mode 100644 index 0000000000..2b0812d4f1 --- /dev/null +++ b/js/src/tests/non262/Function/function-caller.js @@ -0,0 +1,45 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = 'function-caller.js'; +var BUGNUMBER = 514581; +var summary = "Function.prototype.caller should throw a TypeError for " + + "strict-mode functions"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +// behavior + +function expectTypeError(fun) +{ + try + { + fun(); + throw new Error("didn't throw"); + } + catch (e) + { + assertEq(e instanceof TypeError, true, + "expected TypeError calling function" + + ("name" in fun ? " " + fun.name : "") + ", instead got: " + e); + } +} + +function bar() { "use strict"; } +expectTypeError(function barCaller() { bar.caller; }); + +function baz() { "use strict"; return 17; } +expectTypeError(function bazCaller() { baz.caller; }); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Function/function-constructor-toString-arguments-before-parsing-params.js b/js/src/tests/non262/Function/function-constructor-toString-arguments-before-parsing-params.js new file mode 100644 index 0000000000..4e88a00966 --- /dev/null +++ b/js/src/tests/non262/Function/function-constructor-toString-arguments-before-parsing-params.js @@ -0,0 +1,23 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 920479; +var summary = + "Convert all arguments passed to Function() to string before doing any " + + "parsing of the to-be-created Function's parameters or body text"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +assertThrowsValue(() => Function("@", { toString() { throw 42; } }), 42); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Function/function-name-assignment.js b/js/src/tests/non262/Function/function-name-assignment.js new file mode 100644 index 0000000000..5e4d1c004f --- /dev/null +++ b/js/src/tests/non262/Function/function-name-assignment.js @@ -0,0 +1,139 @@ +var BUGNUMBER = 883377; +var summary = "Anonymous function name should be set based on assignment"; + +print(BUGNUMBER + ": " + summary); + +var fooSymbol = Symbol("foo"); +var emptySymbol = Symbol(""); +var undefSymbol = Symbol(); +var globalVar; + +var exprs = [ + ["function() {}", false], + ["function named() {}", true], + ["function*() {}", false], + ["function* named() {}", true], + ["async function() {}", false], + ["async function named() {}", true], + ["() => {}", false], + ["async () => {}", false], + ["class {}", false], + ["class named {}", true], +]; + +function testAssignmentExpression(expr, named) { + eval(` + var assignment; + assignment = ${expr}; + assertEq(assignment.name, named ? "named" : "assignment"); + + globalVar = ${expr}; + assertEq(globalVar.name, named ? "named" : "globalVar"); + + var obj = { dynamic: null }; + with (obj) { + dynamic = ${expr}; + } + assertEq(obj.dynamic.name, named ? "named" : "dynamic"); + + (function namedLambda(param1, param2) { + var assignedToNamedLambda; + assignedToNamedLambda = namedLambda = ${expr}; + assertEq(namedLambda.name, "namedLambda"); + assertEq(assignedToNamedLambda.name, named ? "named" : "namedLambda"); + + param1 = ${expr}; + assertEq(param1.name, named ? "named" : "param1"); + + { + let param1 = ${expr}; + assertEq(param1.name, named ? "named" : "param1"); + + param2 = ${expr}; + assertEq(param2.name, named ? "named" : "param2"); + } + })(); + + { + let nextedLexical1, nextedLexical2; + { + let nextedLexical1 = ${expr}; + assertEq(nextedLexical1.name, named ? "named" : "nextedLexical1"); + + nextedLexical2 = ${expr}; + assertEq(nextedLexical2.name, named ? "named" : "nextedLexical2"); + } + } + `); + + // Not applicable cases: not IsIdentifierRef. + eval(` + var inParen; + (inParen) = ${expr}; + assertEq(inParen.name, named ? "named" : ""); + `); + + // Not applicable cases: not direct RHS. + if (!expr.includes("=>")) { + eval(` + var a = true && ${expr}; + assertEq(a.name, named ? "named" : ""); + `); + } else { + // Arrow function cannot be RHS of &&. + eval(` + var a = true && (${expr}); + assertEq(a.name, named ? "named" : ""); + `); + } + + // Not applicable cases: property. + eval(` + var obj = {}; + + obj.prop = ${expr}; + assertEq(obj.prop.name, named ? "named" : ""); + + obj["literal"] = ${expr}; + assertEq(obj["literal"].name, named ? "named" : ""); + `); + + // Not applicable cases: assigned again. + eval(` + var tmp = [${expr}]; + assertEq(tmp[0].name, named ? "named" : ""); + + var assignment; + assignment = tmp[0]; + assertEq(assignment.name, named ? "named" : ""); + `); +} +for (var [expr, named] of exprs) { + testAssignmentExpression(expr, named); +} + +function testVariableDeclaration(expr, named) { + eval(` + var varDecl = ${expr}; + assertEq(varDecl.name, named ? "named" : "varDecl"); + `); +} +for (var [expr, named] of exprs) { + testVariableDeclaration(expr, named); +} + +function testLexicalBinding(expr, named) { + eval(` + let lexical = ${expr}; + assertEq(lexical.name, named ? "named" : "lexical"); + + const constLexical = ${expr}; + assertEq(constLexical.name, named ? "named" : "constLexical"); + `); +} +for (var [expr, named] of exprs) { + testLexicalBinding(expr, named); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Function/function-name-binding.js b/js/src/tests/non262/Function/function-name-binding.js new file mode 100644 index 0000000000..bdd6c131c0 --- /dev/null +++ b/js/src/tests/non262/Function/function-name-binding.js @@ -0,0 +1,54 @@ +var BUGNUMBER = 883377; +var summary = "Anonymous function name should be set based on binding pattern"; + +print(BUGNUMBER + ": " + summary); + +var exprs = [ + ["function() {}", false], + ["function named() {}", true], + ["function*() {}", false], + ["function* named() {}", true], + ["async function() {}", false], + ["async function named() {}", true], + ["() => {}", false], + ["async () => {}", false], + ["class {}", false], + ["class named {}", true], +]; + +function testAssignmentProperty(expr, named) { + var f = eval(`(function({ prop1 = ${expr} }) { return prop1; })`); + assertEq(f({}).name, named ? "named" : "prop1"); + + eval(` + var { prop1 = ${expr} } = {}; + assertEq(prop1.name, named ? "named" : "prop1"); + `); +} +for (var [expr, named] of exprs) { + testAssignmentProperty(expr, named); +} + +function testAssignmentElement(expr, named) { + var f = eval(`(function([elem1 = ${expr}]) { return elem1; })`); + assertEq(f([]).name, named ? "named" : "elem1"); + + eval(` + var [elem1 = ${expr}] = []; + assertEq(elem1.name, named ? "named" : "elem1"); + `); +} +for (var [expr, named] of exprs) { + testAssignmentElement(expr, named); +} + +function testSingleNameBinding(expr, named) { + var f = eval(`(function(param1 = ${expr}) { return param1; })`); + assertEq(f().name, named ? "named" : "param1"); +} +for (var [expr, named] of exprs) { + testSingleNameBinding(expr, named); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Function/function-name-class.js b/js/src/tests/non262/Function/function-name-class.js new file mode 100644 index 0000000000..edde690556 --- /dev/null +++ b/js/src/tests/non262/Function/function-name-class.js @@ -0,0 +1,32 @@ +var BUGNUMBER = 883377; +var summary = "Anonymous class with name method shouldn't be affected by assignment"; + +print(BUGNUMBER + ": " + summary); + +var classWithStaticNameMethod = class { static name() {} }; +assertEq(typeof classWithStaticNameMethod.name, "function"); + +var classWithStaticNameGetter = class { static get name() { return "static name"; } }; +assertEq(typeof Object.getOwnPropertyDescriptor(classWithStaticNameGetter, "name").get, "function"); +assertEq(classWithStaticNameGetter.name, "static name"); + +var classWithStaticNameSetter = class { static set name(v) {} }; +assertEq(typeof Object.getOwnPropertyDescriptor(classWithStaticNameSetter, "name").set, "function"); + +var n = "NAME".toLowerCase(); +var classWithStaticNameMethodComputed = class { static [n]() {} }; +assertEq(typeof classWithStaticNameMethodComputed.name, "function"); + +// It doesn't apply for non-static method. + +var classWithNameMethod = class { name() {} }; +assertEq(classWithNameMethod.name, "classWithNameMethod"); + +var classWithNameGetter = class { get name() { return "name"; } }; +assertEq(classWithNameGetter.name, "classWithNameGetter"); + +var classWithNameSetter = class { set name(v) {} }; +assertEq(classWithNameSetter.name, "classWithNameSetter"); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Function/function-name-computed-01.js b/js/src/tests/non262/Function/function-name-computed-01.js new file mode 100644 index 0000000000..ee74dfd6bb --- /dev/null +++ b/js/src/tests/non262/Function/function-name-computed-01.js @@ -0,0 +1,57 @@ +var obj = { + ["func"]: function() {}, + ["genFunc"]: function*() {}, + ["asyncFunc"]: async function() {}, + ["asyncGenFunc"]: async function*() {}, + ["arrowFunc"]: ()=>{}, + ["asyncArrowFunc"]: async ()=>{}, + ["method"]() {}, + ["anonClass"]: class {}, + ["nonAnonymousFunc"]: function F() {}, + ["nonAnonymousClass"]: class C{}, + get ["getter"]() {}, + set ["setter"](x) {}, +}; + +assertEq(obj.func.name, "func"); +assertEq(obj.genFunc.name, "genFunc"); +assertEq(obj.asyncFunc.name, "asyncFunc"); +assertEq(obj.asyncGenFunc.name, "asyncGenFunc"); +assertEq(obj.arrowFunc.name, "arrowFunc"); +assertEq(obj.asyncArrowFunc.name, "asyncArrowFunc"); +assertEq(obj.method.name, "method"); +assertEq(obj.anonClass.name, "anonClass"); +assertEq(obj.nonAnonymousFunc.name, "F"); +assertEq(obj.nonAnonymousClass.name, "C"); + +assertEq(Object.getOwnPropertyDescriptor(obj, "getter").get.name, "get getter"); +assertEq(Object.getOwnPropertyDescriptor(obj, "setter").set.name, "set setter"); + +let dummy = class { + ["func"]() {} + *["genFunc"] () {} + async ["asyncFunc"]() {} + async *["asyncGenFunc"]() {} + ["arrowFunc"] = ()=>{} + ["asyncArrowFunc"] = async ()=>{}; + ["method"]() {} + get ["getter"]() {} + set ["setter"](x) {} +}; + +dum = new dummy(); + +assertEq(dum.func.name, "func"); +assertEq(dum.genFunc.name, "genFunc"); +assertEq(dum.asyncFunc.name, "asyncFunc"); +assertEq(dum.asyncGenFunc.name, "asyncGenFunc"); +assertEq(dum.arrowFunc.name, "arrowFunc"); +assertEq(dum.asyncArrowFunc.name, "asyncArrowFunc"); +assertEq(dum.method.name, "method"); + +assertEq(Object.getOwnPropertyDescriptor(dummy.prototype, "getter").get.name, "get getter"); +assertEq(Object.getOwnPropertyDescriptor(dummy.prototype, "setter").set.name, "set setter"); + +if (typeof reportCompare === "function") + reportCompare(true, true); + diff --git a/js/src/tests/non262/Function/function-name-computed-02.js b/js/src/tests/non262/Function/function-name-computed-02.js new file mode 100644 index 0000000000..54048aee49 --- /dev/null +++ b/js/src/tests/non262/Function/function-name-computed-02.js @@ -0,0 +1,57 @@ +var obj = { + [1]: function() {}, + [2]: function*() {}, + [3]: async function() {}, + [4]: async function*() {}, + [5]: ()=>{}, + [6]: async ()=>{}, + [7] () {}, + [8]: class {}, + [9]: function F() {}, + [10]: class C{}, + get [11]() {}, + set [12](x) {}, +}; + +assertEq(obj[1].name, "1"); +assertEq(obj[2].name, "2"); +assertEq(obj[3].name, "3"); +assertEq(obj[4].name, "4"); +assertEq(obj[5].name, "5"); +assertEq(obj[6].name, "6"); +assertEq(obj[7].name, "7"); +assertEq(obj[8].name, "8"); +assertEq(obj[9].name, "F"); +assertEq(obj[10].name, "C"); +assertEq(Object.getOwnPropertyDescriptor(obj, "11").get.name, "get 11"); +assertEq(Object.getOwnPropertyDescriptor(obj, "12").set.name, "set 12"); + +let dummy = class { + [1]() {} + *[2]() {} + async [3]() {} + async *[4]() {} + [5] = ()=>{} + [6] = async ()=>{}; + [7] () {} + get [11]() {} + set [12](x) {} +}; + +dum = new dummy(); + +assertEq(dum[1].name, "1"); +assertEq(dum[2].name, "2"); +assertEq(dum[3].name, "3"); +assertEq(dum[4].name, "4"); +assertEq(dum[5].name, "5"); +assertEq(dum[6].name, "6"); +assertEq(dum[7].name, "7"); + +assertEq(Object.getOwnPropertyDescriptor(dummy.prototype, "11").get.name, "get 11"); +assertEq(Object.getOwnPropertyDescriptor(dummy.prototype, "12").set.name, "set 12"); + + +if (typeof reportCompare === "function") + reportCompare(true, true); + diff --git a/js/src/tests/non262/Function/function-name-for.js b/js/src/tests/non262/Function/function-name-for.js new file mode 100644 index 0000000000..2f04a5fa8d --- /dev/null +++ b/js/src/tests/non262/Function/function-name-for.js @@ -0,0 +1,31 @@ +var BUGNUMBER = 883377; +var summary = "Anonymous function name should be set based on for-in initializer"; + +print(BUGNUMBER + ": " + summary); + +var exprs = [ + ["function() {}", false], + ["function named() {}", true], + ["function*() {}", false], + ["function* named() {}", true], + ["async function() {}", false], + ["async function named() {}", true], + ["() => {}", false], + ["async () => {}", false], + ["class {}", false], + ["class named {}", true], +]; + +function testForInHead(expr, named) { + eval(` + for (var forInHead = ${expr} in {}) { + } + `); + assertEq(forInHead.name, named ? "named" : "forInHead"); +} +for (var [expr, named] of exprs) { + testForInHead(expr, named); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Function/function-name-method.js b/js/src/tests/non262/Function/function-name-method.js new file mode 100644 index 0000000000..3b2eeee793 --- /dev/null +++ b/js/src/tests/non262/Function/function-name-method.js @@ -0,0 +1,70 @@ +var BUGNUMBER = 883377; +var summary = "Anonymous function name should be set based on method definition"; + +print(BUGNUMBER + ": " + summary); + +var fooSymbol = Symbol("foo"); +var emptySymbol = Symbol(""); +var undefSymbol = Symbol(); + +function testMethod(prefix, classPrefix="", prototype=false) { + var param = (prefix == "set" || prefix == "static set") ? "v" : ""; + var sep = classPrefix ? "" : ","; + var objOrClass = eval(`(${classPrefix}{ + ${prefix} prop(${param}) {} ${sep} + ${prefix} "literal"(${param}) {} ${sep} + ${prefix} ""(${param}) {} ${sep} + ${prefix} 5(${param}) {} ${sep} + ${prefix} [Symbol.iterator](${param}) {} ${sep} + ${prefix} [fooSymbol](${param}) {} ${sep} + ${prefix} [emptySymbol](${param}) {} ${sep} + ${prefix} [undefSymbol](${param}) {} ${sep} + ${prefix} [/a/](${param}) {} ${sep} + })`); + + var target = prototype ? objOrClass.prototype : objOrClass; + + function testOne(methodName, expectedName) { + var f; + if (prefix == "get" || prefix == "static get") { + f = Object.getOwnPropertyDescriptor(target, methodName).get; + expectedName = "get " + expectedName; + } else if (prefix == "set" || prefix == "static set") { + f = Object.getOwnPropertyDescriptor(target, methodName).set; + expectedName = "set " + expectedName; + } else { + f = Object.getOwnPropertyDescriptor(target, methodName).value; + } + + assertEq(f.name, expectedName); + } + testOne("prop", "prop"); + testOne("literal", "literal"); + testOne("", ""); + testOne(5, "5"); + testOne(Symbol.iterator, "[Symbol.iterator]"); + testOne(fooSymbol, "[foo]"); + testOne(emptySymbol, "[]"); + testOne(undefSymbol, ""); + testOne(/a/, "/a/"); +} +testMethod(""); +testMethod("*"); +testMethod("async"); +testMethod("get"); +testMethod("set"); + +testMethod("", "class", true); +testMethod("*", "class", true); +testMethod("async", "class", true); +testMethod("get", "class", true); +testMethod("set", "class", true); + +testMethod("static", "class"); +testMethod("static *", "class"); +testMethod("static async", "class"); +testMethod("static get", "class"); +testMethod("static set", "class"); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Function/function-name-property.js b/js/src/tests/non262/Function/function-name-property.js new file mode 100644 index 0000000000..7ad174b10f --- /dev/null +++ b/js/src/tests/non262/Function/function-name-property.js @@ -0,0 +1,58 @@ +var BUGNUMBER = 883377; +var summary = "Anonymous function name should be set based on property name"; + +print(BUGNUMBER + ": " + summary); + +var fooSymbol = Symbol("foo"); +var emptySymbol = Symbol(""); +var undefSymbol = Symbol(); + +var exprs = [ + ["function() {}", false], + ["function named() {}", true], + ["function*() {}", false], + ["function* named() {}", true], + ["async function() {}", false], + ["async function named() {}", true], + ["() => {}", false], + ["async () => {}", false], + ["class {}", false], + ["class named {}", true], +]; + +function testPropertyDefinition(expr, named) { + var obj = eval(`({ + prop: ${expr}, + "literal": ${expr}, + "": ${expr}, + 5: ${expr}, + 0.4: ${expr}, + [Symbol.iterator]: ${expr}, + [fooSymbol]: ${expr}, + [emptySymbol]: ${expr}, + [undefSymbol]: ${expr}, + [/a/]: ${expr}, + })`); + assertEq(obj.prop.name, named ? "named" : "prop"); + assertEq(obj["literal"].name, named ? "named" : "literal"); + assertEq(obj[""].name, named ? "named" : ""); + assertEq(obj[5].name, named ? "named" : "5"); + assertEq(obj[0.4].name, named ? "named" : "0.4"); + assertEq(obj[Symbol.iterator].name, named ? "named" : "[Symbol.iterator]"); + assertEq(obj[fooSymbol].name, named ? "named" : "[foo]"); + assertEq(obj[emptySymbol].name, named ? "named" : "[]"); + assertEq(obj[undefSymbol].name, named ? "named" : ""); + assertEq(obj[/a/].name, named ? "named" : "/a/"); + + // Not applicable cases: __proto__. + obj = { + __proto__: function() {} + }; + assertEq(obj.__proto__.name, ""); +} +for (var [expr, named] of exprs) { + testPropertyDefinition(expr, named); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Function/function-name.js b/js/src/tests/non262/Function/function-name.js new file mode 100644 index 0000000000..7beca56df5 --- /dev/null +++ b/js/src/tests/non262/Function/function-name.js @@ -0,0 +1,64 @@ +function testFunctionName(f) { + var name = f.name; + f.name = 'g'; + assertEq(f.name, name); + assertEq(delete f.name, true); + assertEq(f.name, ''); + assertEq(f.hasOwnProperty('name'), false); + f.name = 'g'; + assertEq(f.name, ''); + Object.defineProperty(f, 'name', {value: 'g'}); + assertEq(f.name, 'g'); +} +function testFunctionNameStrict(f) { + "use strict"; + var name = f.name; + var error; + try { + f.name = 'g'; + } catch (e) { + error = e; + } + assertEq(f.name, name); + assertEq(error instanceof TypeError, true); + assertEq(delete f.name, true); + assertEq(f.name, ''); + assertEq(f.hasOwnProperty('name'), false); + error = null; + try { + f.name = 'g'; + } catch (e) { + error = e; + } + assertEq(f.name, ''); + assertEq(error instanceof TypeError, true); + Object.defineProperty(f, 'name', {value: 'g'}); + assertEq(f.name, 'g'); +} + +assertEq(Object.getOwnPropertyDescriptor(Object, "name").writable, false); +assertEq(Object.getOwnPropertyDescriptor(Object, "name").enumerable, false); +assertEq(Object.getOwnPropertyDescriptor(Object, "name").configurable, true); +assertEq(Object.getOwnPropertyDescriptor(Object, "name").value, 'Object'); +assertEq(Object.getOwnPropertyDescriptor(function f(){}, "name").writable, false); +assertEq(Object.getOwnPropertyDescriptor(function f(){}, "name").enumerable, false); +assertEq(Object.getOwnPropertyDescriptor(function f(){}, "name").configurable, true); +assertEq(Object.getOwnPropertyDescriptor(function f(){}, "name").value, 'f'); + +// Basic test ensuring that Object.defineProperty works on pristine function. +function f() {}; +Object.defineProperty(f, 'name', {value: 'g'}); +assertEq(f.name, 'g'); + +// .name behaves as expected on scripted function. +testFunctionName(function f(){}); +testFunctionNameStrict(function f(){}); +// .name behaves as expected on builtin function. +testFunctionName(Function.prototype.apply); +testFunctionNameStrict(Function.prototype.call); +// .name behaves as expected on self-hosted builtin function. +testFunctionName(Array.prototype.forEach); +testFunctionNameStrict(Array.prototype.some); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Function/function-toString-builtin-name.js b/js/src/tests/non262/Function/function-toString-builtin-name.js new file mode 100644 index 0000000000..709e7e846b --- /dev/null +++ b/js/src/tests/non262/Function/function-toString-builtin-name.js @@ -0,0 +1,53 @@ +// Repeats the test from 'Function/function-toString-builtin.js' and additionally +// verifies the name matches the expected value. +// +// This behaviour is not required by the ECMAScript standard. + +// Greatly (!) simplified patterns for the PropertyName production. +var propertyName = [ + // PropertyName :: LiteralPropertyName :: IdentifierName + "\\w+", + + // PropertyName :: LiteralPropertyName :: StringLiteral + "(?:'[^']*')", + "(?:\"[^\"]*\")", + + // PropertyName :: LiteralPropertyName :: NumericLiteral + "\\d+", + + // PropertyName :: ComputedPropertyName + "(?:\\[[^\\]]+\\])", +].join("|") + +var nativeCode = RegExp([ + "^", "function", ("(" + propertyName + ")?"), "\\(", "\\)", "\\{", "\\[native code\\]", "\\}", "$" +].join("\\s*")); + +function assertFunctionName(fun, expected) { + var match = nativeCode.exec(fun.toString()); + assertEq(match[1], expected); +} + +// Bound functions are considered built-ins. +assertFunctionName(function(){}.bind(), undefined); +assertFunctionName(function fn(){}.bind(), undefined); + +// Built-ins which are well-known intrinsic objects. +assertFunctionName(Array, "Array"); +assertFunctionName(Object.prototype.toString, "toString"); +assertFunctionName(decodeURI, "decodeURI"); + +// Other built-in functions. +assertFunctionName(Math.asin, "asin"); +assertFunctionName(String.prototype.blink, "blink"); +assertFunctionName(RegExp.prototype[Symbol.split], "[Symbol.split]"); + +// Built-in getter functions. +assertFunctionName(Object.getOwnPropertyDescriptor(RegExp.prototype, "flags").get, "flags"); +assertFunctionName(Object.getOwnPropertyDescriptor(Object.prototype, "__proto__").get, "__proto__"); + +// Built-in setter functions. +assertFunctionName(Object.getOwnPropertyDescriptor(Object.prototype, "__proto__").set, "__proto__"); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Function/function-toString-builtin.js b/js/src/tests/non262/Function/function-toString-builtin.js new file mode 100644 index 0000000000..d4efc81c14 --- /dev/null +++ b/js/src/tests/non262/Function/function-toString-builtin.js @@ -0,0 +1,42 @@ + +// Greatly (!) simplified patterns for the PropertyName production. +var propertyName = [ + // PropertyName :: LiteralPropertyName :: IdentifierName + "\\w+", + + // PropertyName :: LiteralPropertyName :: StringLiteral + "(?:'[^']*')", + "(?:\"[^\"]*\")", + + // PropertyName :: LiteralPropertyName :: NumericLiteral + "\\d+", + + // PropertyName :: ComputedPropertyName + "(?:\\[[^\\]]+\\])", +].join("|") + +var nativeCode = RegExp([ + "^", "function", ("(?:" + propertyName + ")?"), "\\(", "\\)", "\\{", "\\[native code\\]", "\\}", "$" +].join("\\s*")); + + +// Bound functions are considered built-ins. +reportMatch(nativeCode, function(){}.bind().toString()); +reportMatch(nativeCode, function fn(){}.bind().toString()); + +// Built-ins which are well-known intrinsic objects. +reportMatch(nativeCode, Array.toString()); +reportMatch(nativeCode, Object.prototype.toString.toString()); +reportMatch(nativeCode, decodeURI.toString()); + +// Other built-in functions. +reportMatch(nativeCode, Math.asin.toString()); +reportMatch(nativeCode, String.prototype.blink.toString()); +reportMatch(nativeCode, RegExp.prototype[Symbol.split].toString()); + +// Built-in getter functions. +reportMatch(nativeCode, Object.getOwnPropertyDescriptor(RegExp.prototype, "flags").get.toString()); +reportMatch(nativeCode, Object.getOwnPropertyDescriptor(Object.prototype, "__proto__").get.toString()); + +// Built-in setter functions. +reportMatch(nativeCode, Object.getOwnPropertyDescriptor(Object.prototype, "__proto__").set.toString()); diff --git a/js/src/tests/non262/Function/get-function-realm.js b/js/src/tests/non262/Function/get-function-realm.js new file mode 100644 index 0000000000..4efd94f971 --- /dev/null +++ b/js/src/tests/non262/Function/get-function-realm.js @@ -0,0 +1,45 @@ +var g1 = newGlobal(); +var g1Fun = g1.eval("function Fun() {}; Fun"); + +// Bound function => cross-realm function. +var bound1 = Function.prototype.bind.call(g1Fun); +assertEq(Object.getPrototypeOf(new bound1()), g1.Fun.prototype); + +// Proxy => cross-realm function. +var proxy1 = new Proxy(g1Fun, { + get: function() {} // Ensure "prototype" is |undefined|. +}); +assertEq(Object.getPrototypeOf(new proxy1()), g1.Object.prototype); + +// Proxy => bound function => cross-realm function. +var proxy2 = new Proxy(bound1, { + get: function() {} +}); +assertEq(Object.getPrototypeOf(new proxy2()), g1.Object.prototype); + +// Revoked proxy => cross-realm function. +var r1 = Proxy.revocable(g1Fun, { + get: function(t, name) { + assertEq(name, "prototype"); + r1.revoke(); + } +}); +assertThrowsInstanceOf(() => new r1.proxy(), g1.TypeError); + +// Bound function => proxy => bound function => cross-realm function. +var bound2 = Function.prototype.bind.call(proxy2); +assertEq(Object.getPrototypeOf(new bound2()), g1.Object.prototype); + +// Proxy => cross-realm revoked proxy => cross-realm function. +var r2 = Proxy.revocable(g1Fun, { + get: function(t, name) { + assertEq(name, "prototype"); + r2.revoke(); + } +}); +var g2 = newGlobal(); +var proxy3 = new g2.Proxy(r2.proxy, {}); +assertThrowsInstanceOf(() => new proxy3(), g1.TypeError); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Function/has-instance-jitted.js b/js/src/tests/non262/Function/has-instance-jitted.js new file mode 100644 index 0000000000..a2d33abc7f --- /dev/null +++ b/js/src/tests/non262/Function/has-instance-jitted.js @@ -0,0 +1,96 @@ +const OriginalHasInstance = Function.prototype[Symbol.hasInstance]; + +// Ensure that folding doesn't impact user defined @@hasInstance methods. +{ + function Test() { + this.x = 1; + } + + Object.defineProperty(Test, Symbol.hasInstance, + {writable: true, value: () => false}); + + function x(t) { + return t instanceof Test; + } + + function y() { + let t = new Test; + let b = true; + for (let i = 0; i < 10; i++) { + b = b && x(t); + } + return b; + } + + + function z() { + let f = 0; + let t = 0; + for (let i = 0; i < 100; i++) + assertEq(y(), false); + } + + z(); +} + +// Ensure that the jitting does not clobber user defined @@hasInstance methods. +{ + function a() { + function b() {}; + b.__proto__ = a.prototype; + return b; + }; + let c = new a(); + + let t = 0; + let f = 0; + let e = 0; + for (let i = 0; i < 40000; i++) { + if (i == 20000) + Object.defineProperty(a.prototype, Symbol.hasInstance, + {writable: true, value: () => true}); + if (i == 30000) + Object.setPrototypeOf(c, Function.prototype); + + if (1 instanceof c) { + t++; + } else { + f++; + } + } + + assertEq(t, 10000); + assertEq(f, 30000); +} + +{ + function a() {}; + function b() {}; + Object.defineProperty(a, Symbol.hasInstance, {writable: true, value: () => true}); + assertEq(b instanceof a, true); + for (let _ of Array(10000)) + assertEq(b instanceof a, true); +} + +{ + function a(){}; + function b(){}; + function c(){}; + function d(){}; + function e(){}; + Object.defineProperty(a, Symbol.hasInstance, {value: () => true }); + Object.defineProperty(b, Symbol.hasInstance, {value: () => true }); + Object.defineProperty(c, Symbol.hasInstance, {value: () => true }); + Object.defineProperty(d, Symbol.hasInstance, {value: () => true }); + let funcs = [a, b, c, d]; + for (let f of funcs) + assertEq(e instanceof f, true); + + for (let _ of Array(10001)) { + for (let f of funcs) + assertEq(e instanceof f, true); + } +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Function/has-instance.js b/js/src/tests/non262/Function/has-instance.js new file mode 100644 index 0000000000..f0c7bf28e1 --- /dev/null +++ b/js/src/tests/non262/Function/has-instance.js @@ -0,0 +1,101 @@ +// It is possible to override Function.prototype[@@hasInstance]. +let passed = false; +let obj = { foo: true }; +let C = function(){}; + +Object.defineProperty(C, Symbol.hasInstance, { + value: function(inst) { passed = inst.foo; return false; } +}); + +assertEq(obj instanceof C, false); +assertEq(passed, true); + +{ + let obj = { + [Symbol.hasInstance](v) { return true; }, + }; + let whatevs = {}; + assertEq(whatevs instanceof obj, true); +} + +{ + + function zzzz() {}; + let xxxx = new zzzz(); + assertEq(xxxx instanceof zzzz, true); + assertEq(zzzz[Symbol.hasInstance](xxxx), true); + +} + +// Non-callable objects should return false. +const nonCallables = [ + 1, + undefined, + null, + "nope", +] + +for (let nonCallable of nonCallables) { + assertEq(nonCallable instanceof Function, false); + assertEq(nonCallable instanceof Object, false); +} + +// Non-callables should throw when used on the right hand side +// of `instanceof`. +assertThrowsInstanceOf(() => { + function foo() {}; + let obj = {}; + foo instanceof obj; +}, TypeError); + +// Non-callables do not throw for overridden methods +let o = {[Symbol.hasInstance](v) { return true; }} +assertEq(1 instanceof o, true); + +// Non-callables return false instead of an exception when +// Function.prototype[Symbol.hasInstance] is called directly. +for (let nonCallable of nonCallables) { + assertEq(Function.prototype[Symbol.hasInstance].call(nonCallable, Object), false); +} + +// It should be possible to call the Symbol.hasInstance method directly. +assertEq(Function.prototype[Symbol.hasInstance].call(Function, () => 1), true); +assertEq(Function.prototype[Symbol.hasInstance].call(Function, Object), true); +assertEq(Function.prototype[Symbol.hasInstance].call(Function, null), false); +assertEq(Function.prototype[Symbol.hasInstance].call(Function, Array), true); +assertEq(Function.prototype[Symbol.hasInstance].call(Object, Array), true); +assertEq(Function.prototype[Symbol.hasInstance].call(Array, Function), false); +assertEq(Function.prototype[Symbol.hasInstance].call(({}), Function), false); +assertEq(Function.prototype[Symbol.hasInstance].call(), false) +assertEq(Function.prototype[Symbol.hasInstance].call(({})), false) + +// Ensure that bound functions are unwrapped properly +let bindme = {x: function() {}}; +let instance = new bindme.x(); +let xOuter = bindme.x; +let bound = xOuter.bind(bindme); +let doubleBound = bound.bind(bindme); +let tripleBound = bound.bind(doubleBound); +assertEq(Function.prototype[Symbol.hasInstance].call(bound, instance), true); +assertEq(Function.prototype[Symbol.hasInstance].call(doubleBound, instance), true); +assertEq(Function.prototype[Symbol.hasInstance].call(tripleBound, instance), true); + +// Function.prototype[Symbol.hasInstance] is not configurable +let desc = Object.getOwnPropertyDescriptor(Function.prototype, Symbol.hasInstance); +assertEq(desc.configurable, false); + +// Attempting to use a non-callable @@hasInstance triggers a type error +// Bug 1280892 +assertThrowsInstanceOf(() => { + var fun = function() {} + var p = new Proxy(fun, { + get(target, key) { + return /not-callable/; + } + }); + fun instanceof p; +}, TypeError); + + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Function/implicit-this-in-parameter-expression.js b/js/src/tests/non262/Function/implicit-this-in-parameter-expression.js new file mode 100644 index 0000000000..c58c53e2af --- /dev/null +++ b/js/src/tests/non262/Function/implicit-this-in-parameter-expression.js @@ -0,0 +1,18 @@ + +function f(a = eval(` + function g() { + 'use strict'; + return this; + } + + with ({}) { + g() /* implicit return value */ + } + `)) { + return a +}; + +assertEq(f(), undefined); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Function/invalid-parameter-list.js b/js/src/tests/non262/Function/invalid-parameter-list.js new file mode 100644 index 0000000000..8aae89ef15 --- /dev/null +++ b/js/src/tests/non262/Function/invalid-parameter-list.js @@ -0,0 +1,27 @@ +// This constructor behaves like `Function` without checking +// if the parameter list end is at the expected position. +// We use this to make sure that the tests we use are otherwise +// syntactically correct. +function DumpFunction(...args) { + let code = "function anonymous("; + code += args.slice(0, -1).join(", "); + code += ") {\n"; + code += args[args.length -1]; + code += "\n}"; + eval(code); +} + +const tests = [ + ["/*", "*/) {"], + ["//", ") {"], + ["a = `", "` ) {"], + [") { var x = function (", "} "], + ["x = function (", "}) {"] +]; + +for (const test of tests) { + DumpFunction(...test); + assertThrowsInstanceOf(() => new Function(...test), SyntaxError); +} + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Function/length-with-destructuring-and-parameter-expression.js b/js/src/tests/non262/Function/length-with-destructuring-and-parameter-expression.js new file mode 100644 index 0000000000..a3f00ac1f2 --- /dev/null +++ b/js/src/tests/non262/Function/length-with-destructuring-and-parameter-expression.js @@ -0,0 +1,31 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +assertEq(function([a = 0]){}.length, 1); +assertEq(function({p: a = 0}){}.length, 1); +assertEq(function({a = 0}){}.length, 1); +assertEq(function({[0]: a}){}.length, 1); + +assertEq(function([a = 0], [b = 0]){}.length, 2); +assertEq(function({p: a = 0}, [b = 0]){}.length, 2); +assertEq(function({a = 0}, [b = 0]){}.length, 2); +assertEq(function({[0]: a}, [b = 0]){}.length, 2); + +assertEq(function(x, [a = 0]){}.length, 2); +assertEq(function(x, {p: a = 0}){}.length, 2); +assertEq(function(x, {a = 0}){}.length, 2); +assertEq(function(x, {[0]: a}){}.length, 2); + +assertEq(function(x = 0, [a = 0]){}.length, 0); +assertEq(function(x = 0, {p: a = 0}){}.length, 0); +assertEq(function(x = 0, {a = 0}){}.length, 0); +assertEq(function(x = 0, {[0]: a}){}.length, 0); + +assertEq(function([a = 0], ...r){}.length, 1); +assertEq(function({p: a = 0}, ...r){}.length, 1); +assertEq(function({a = 0}, ...r){}.length, 1); +assertEq(function({[0]: a}, ...r){}.length, 1); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Function/line-terminator-before-arrow.js b/js/src/tests/non262/Function/line-terminator-before-arrow.js new file mode 100644 index 0000000000..52bdce7f3b --- /dev/null +++ b/js/src/tests/non262/Function/line-terminator-before-arrow.js @@ -0,0 +1,9 @@ +assertThrowsInstanceOf(() => eval("() \n => {}"), SyntaxError); +assertThrowsInstanceOf(() => eval("a \n => {}"), SyntaxError); +assertThrowsInstanceOf(() => eval("(a) /*\n*/ => {}"), SyntaxError); +assertThrowsInstanceOf(() => eval("(a, b) \n => {}"), SyntaxError); +assertThrowsInstanceOf(() => eval("(a, b = 1) \n => {}"), SyntaxError); +assertThrowsInstanceOf(() => eval("(a, ...b) \n => {}"), SyntaxError); +assertThrowsInstanceOf(() => eval("(a, b = 1, ...c) \n => {}"), SyntaxError); + +reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Function/method-has-duplicated.js b/js/src/tests/non262/Function/method-has-duplicated.js new file mode 100644 index 0000000000..dc0a9dfb42 --- /dev/null +++ b/js/src/tests/non262/Function/method-has-duplicated.js @@ -0,0 +1,19 @@ +// Make sure duplicated name is allowed in non-strict. +function f0(a) { +} + +// SyntaxError should be thrown if method definition has duplicated name. +assertThrowsInstanceOf(() => eval(` +({ + m1(a, a) { + } +}); +`), SyntaxError); +assertThrowsInstanceOf(() => eval(` +({ + m2(a, ...a) { + } +}); +`), SyntaxError); + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Function/parameter-redeclaration.js b/js/src/tests/non262/Function/parameter-redeclaration.js new file mode 100644 index 0000000000..74e55e3aa9 --- /dev/null +++ b/js/src/tests/non262/Function/parameter-redeclaration.js @@ -0,0 +1,19 @@ +// 'var' is allowed to redeclare parameters. +function f1(a = 0) { + var a; +} + +// 'let' and 'const' at body-level are not allowed to redeclare parameters. +assertThrowsInstanceOf(() => { + eval(`function f2(a = 0) { + let a; + }`); +}, SyntaxError); +assertThrowsInstanceOf(() => { + eval(`function f3(a = 0) { + const a; + }`); +}, SyntaxError); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Function/redefine-arguments-length.js b/js/src/tests/non262/Function/redefine-arguments-length.js new file mode 100644 index 0000000000..ad9ae742ff --- /dev/null +++ b/js/src/tests/non262/Function/redefine-arguments-length.js @@ -0,0 +1,65 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = 'redefine-arguments-length.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 539766; +var summary = + "Object.defineProperty sets arguments.length without setting the " + + "length-overridden bit"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function test_JSOP_ARGCNT() +{ + var length = "length"; + Object.defineProperty(arguments, length, { value: 17 }); + assertEq(arguments.length, 17); + assertEq(arguments[length], 17); +} +test_JSOP_ARGCNT(); + +function test_js_fun_apply() +{ + var length = "length"; + Object.defineProperty(arguments, length, { value: 17 }); + + function fun() + { + assertEq(arguments.length, 17); + assertEq(arguments[length], 17); + assertEq(arguments[0], "foo"); + for (var i = 1; i < 17; i++) + assertEq(arguments[i], undefined); + } + fun.apply(null, arguments); +} +test_js_fun_apply("foo"); + +function test_array_toString_sub_1() +{ + Object.defineProperty(arguments, "length", { value: 1 }); + arguments.join = [].join; + assertEq([].toString.call(arguments), "1"); +} +test_array_toString_sub_1(1, 2); + +function test_array_toString_sub_2() +{ + Object.defineProperty(arguments, "length", { value: 1 }); + assertEq([].toLocaleString.call(arguments), "1"); +} +test_array_toString_sub_2(1, 2); + + +/******************************************************************************/ + +reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Function/regress-123371.js b/js/src/tests/non262/Function/regress-123371.js new file mode 100644 index 0000000000..58294c6a02 --- /dev/null +++ b/js/src/tests/non262/Function/regress-123371.js @@ -0,0 +1,19 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 123371; +var summary = 'Do not crash when newline separates function name from arglist'; +var actual = 'No Crash'; +var expect = 'No Crash'; + + +printBugNumber(BUGNUMBER); +printStatus (summary); + +printStatus +('function call succeeded'); + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/Function/regress-131964.js b/js/src/tests/non262/Function/regress-131964.js new file mode 100644 index 0000000000..d7451f040e --- /dev/null +++ b/js/src/tests/non262/Function/regress-131964.js @@ -0,0 +1,159 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * + * Date: 19 Mar 2002 + * SUMMARY: Function declarations in global or function scope are {DontDelete}. + * Function declarations in eval scope are not {DontDelete}. + * + * See http://bugzilla.mozilla.org/show_bug.cgi?id=131964 + * + */ +//----------------------------------------------------------------------------- +var UBound = 0; +var BUGNUMBER = 131964; +var summary = 'Functions defined in global or function scope are {DontDelete}'; +var status = ''; +var statusitems = []; +var actual = ''; +var actualvalues = []; +var expect= ''; +var expectedvalues = []; + + +status = inSection(1); +function f() +{ + return 'f lives!'; +} +delete f; + +try +{ + actual = f(); +} +catch(e) +{ + actual = 'f was deleted'; +} + +expect = 'f lives!'; +addThis(); + + + +/* + * Try the same test in function scope - + */ +status = inSection(2); +function g() +{ + function f() + { + return 'f lives!'; + } + delete f; + + try + { + actual = f(); + } + catch(e) + { + actual = 'f was deleted'; + } + + expect = 'f lives!'; + addThis(); +} +g(); + + + +/* + * Try the same test in eval scope - here we EXPECT the function to be deleted (?) + */ +status = inSection(3); +var s = ''; +s += 'function h()'; +s += '{ '; +s += ' return "h lives!";'; +s += '}'; +s += 'delete h;'; + +s += 'try'; +s += '{'; +s += ' actual = h();'; +s += '}'; +s += 'catch(e)'; +s += '{'; +s += ' actual = "h was deleted";'; +s += '}'; + +s += 'expect = "h was deleted";'; +s += 'addThis();'; +eval(s); + + +/* + * Define the function in eval scope, but delete it in global scope - + */ +status = inSection(4); +s = ''; +s += 'function k()'; +s += '{ '; +s += ' return "k lives!";'; +s += '}'; +eval(s); + +delete k; + +try +{ + actual = k(); +} +catch(e) +{ + actual = 'k was deleted'; +} + +expect = 'k was deleted'; +addThis(); + + + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + + +function wasDeleted(functionName) +{ + return functionName + ' was deleted...'; +} + + +function addThis() +{ + statusitems[UBound] = status; + actualvalues[UBound] = actual; + expectedvalues[UBound] = expect; + UBound++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus(summary); + + for (var i=0; i Function.prototype.call() ---------> f() + * + * + * The question this bug addresses is, "What should we say |f.caller| is?" + * + * Before this fix, SpiderMonkey said it was |Function.prototype.call|. + * After this fix, SpiderMonkey emulates IE and says |gg| instead. + * + */ +//----------------------------------------------------------------------------- +var UBound = 0; +var BUGNUMBER = 222029; +var summary = "Make our f.caller property match IE's wrt f.apply and f.call"; +var status = ''; +var statusitems = []; +var actual = ''; +var actualvalues = []; +var expect= ''; +var expectedvalues = []; + + +function f() +{ + return f.caller.p ; +} + + +/* + * Call |f| directly + */ +function g() +{ + return f(); +} +g.p = "hello"; + + +/* + * Call |f| via |f.call| + */ +function gg() +{ + return f.call(this); +} +gg.p = "hello"; + + +/* + * Call |f| via |f.apply| + */ +function ggg() +{ + return f.apply(this); +} +ggg.p = "hello"; + + +/* + * Shadow |p| on |Function.prototype.call|, |Function.prototype.apply|. + * In Sections 2 and 3 below, we no longer expect to recover this value - + */ +Function.prototype.call.p = "goodbye"; +Function.prototype.apply.p = "goodbye"; + + + +status = inSection(1); +actual = g(); +expect = "hello"; +addThis(); + +status = inSection(2); +actual = gg(); +expect = "hello"; +addThis(); + +status = inSection(3); +actual = ggg(); +expect = "hello"; +addThis(); + + + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + + +function addThis() +{ + statusitems[UBound] = status; + actualvalues[UBound] = actual; + expectedvalues[UBound] = expect; + UBound++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus(summary); + + for (var i=0; i Function.prototype.call() ---------> f() + * + * + * The question this bug addresses is, "What should we say |f.caller| is?" + * + * Before this fix, SpiderMonkey said it was |Function.prototype.call|. + * After this fix, SpiderMonkey emulates IE and says |gg| instead. + * + */ +//----------------------------------------------------------------------------- +var UBound = 0; +var BUGNUMBER = 222029; +var summary = "Make our f.caller property match IE's wrt f.apply and f.call"; +var status = ''; +var statusitems = []; +var actual = ''; +var actualvalues = []; +var expect= ''; +var expectedvalues = []; + +/* + * Try to confuse the engine by adding a |p| property to everything! + */ +var p = 'global'; +var o = {p:'object'}; + + +function f(obj) +{ + return f.caller.p ; +} + + +/* + * Call |f| directly + */ +function g(obj) +{ + var p = 'local'; + return f(obj); +} +g.p = "hello"; + + +/* + * Call |f| via |f.call| + */ +function gg(obj) +{ + var p = 'local'; + return f.call(obj, obj); +} +gg.p = "hello"; + + +/* + * Call |f| via |f.apply| + */ +function ggg(obj) +{ + var p = 'local'; + return f.apply(obj, [obj]); +} +ggg.p = "hello"; + + +/* + * Shadow |p| on |Function.prototype.call|, |Function.prototype.apply|. + * In Sections 2 and 3 below, we no longer expect to recover this value - + */ +Function.prototype.call.p = "goodbye"; +Function.prototype.apply.p = "goodbye"; + + + +status = inSection(1); +actual = g(o); +expect = "hello"; +addThis(); + +status = inSection(2); +actual = gg(o); +expect = "hello"; +addThis(); + +status = inSection(3); +actual = ggg(o); +expect = "hello"; +addThis(); + + + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + + +function addThis() +{ + statusitems[UBound] = status; + actualvalues[UBound] = actual; + expectedvalues[UBound] = expect; + UBound++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus(summary); + + for (var i=0; i function f\u02B1 () {} + * + * js> f\u02B1.toSource(); + * function f¦() {} + * + * js> f\u02B1.toSource().toSource(); + * (new String("function f\xB1() {}")) + * + * + * See how the high-byte information (the 02) has been lost? + * The same thing was happening with the toString() method: + * + * js> f\u02B1.toString(); + * + * function f¦() { + * } + * + * js> f\u02B1.toString().toSource(); + * (new String("\nfunction f\xB1() {\n}\n")) + * + */ +//----------------------------------------------------------------------------- +var UBound = 0; +var BUGNUMBER = 58274; +var summary = 'Testing functions with double-byte names'; +var ERR = 'UNEXPECTED ERROR! \n'; +var ERR_MALFORMED_NAME = ERR + 'Could not find function name in: \n\n'; +var status = ''; +var statusitems = []; +var actual = ''; +var actualvalues = []; +var expect= ''; +var expectedvalues = []; +var sEval; +var sName; + + +sEval = "function f\u02B2() {return 42;}"; +eval(sEval); +sName = getFunctionName(f\u02B2); + +// Test function call - +status = inSection(1); +actual = f\u02B2(); +expect = 42; +addThis(); + +// Test both characters of function name - +status = inSection(2); +actual = sName[0]; +expect = sEval[9]; +addThis(); + +status = inSection(3); +actual = sName[1]; +expect = sEval[10]; +addThis(); + + + +sEval = "function f\u02B2\u0AAA () {return 84;}"; +eval(sEval); +sName = getFunctionName(f\u02B2\u0AAA); + +// Test function call - +status = inSection(4); +actual = f\u02B2\u0AAA(); +expect = 84; +addThis(); + +// Test all three characters of function name - +status = inSection(5); +actual = sName[0]; +expect = sEval[9]; +addThis(); + +status = inSection(6); +actual = sName[1]; +expect = sEval[10]; +addThis(); + +status = inSection(7); +actual = sName[2]; +expect = sEval[11]; +addThis(); + + + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + + +/* + * Goal: test that f.toString() contains the proper function name. + * + * Note, however, f.toString() is implementation-independent. For example, + * it may begin with '\nfunction' instead of 'function'. Therefore we use + * a regexp to make sure we extract the name properly. + * + * Here we assume that f has been defined by means of a function statement, + * and not a function expression (where it wouldn't have to have a name). + * + * Rhino uses a Unicode representation for f.toString(); whereas + * SpiderMonkey uses an ASCII representation, putting escape sequences + * for non-ASCII characters. For example, if a function is called f\u02B1, + * then in Rhino the toString() method will present a 2-character Unicode + * string for its name, whereas SpiderMonkey will present a 7-character + * ASCII string for its name: the string literal 'f\u02B1'. + * + * So we force the lexer to condense the string before using it. + * This will give uniform results in Rhino and SpiderMonkey. + */ +function getFunctionName(f) +{ + var s = condenseStr(f.toString()); + var re = /\s*function\s+(\S+)\s*\(/; + var arr = s.match(re); + + if (!(arr && arr[1])) + return ERR_MALFORMED_NAME + s; + return arr[1]; +} + + +/* + * This function is the opposite of functions like escape(), which take + * Unicode characters and return escape sequences for them. Here, we force + * the lexer to turn escape sequences back into single characters. + * + * Note we can't simply do |eval(str)|, since in practice |str| will be an + * identifier somewhere in the program (e.g. a function name); thus |eval(str)| + * would return the object that the identifier represents: not what we want. + * + * So we surround |str| lexicographically with quotes to force the lexer to + * evaluate it as a string. Have to strip out any linefeeds first, however - + */ +function condenseStr(str) +{ + /* + * You won't be able to do the next step if |str| has + * any carriage returns or linefeeds in it. For example: + * + * js> eval("'" + '\nHello' + "'"); + * 1: SyntaxError: unterminated string literal: + * 1: ' + * 1: ^ + * + * So replace them with the empty string - + */ + str = str.replace(/[\r\n]/g, '') + return eval("'" + str + "'"); +} + + +function addThis() +{ + statusitems[UBound] = status; + actualvalues[UBound] = actual; + expectedvalues[UBound] = expect; + UBound++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus(summary); + + for (var i=0; i eval(` +function f1(a, ...a) { +} +`), SyntaxError); + +// SyntaxError should be thrown if there is a duplicated parameter. +assertThrowsInstanceOf(() => eval(` +function f2(a, a, ...b) { +} +`), SyntaxError); + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Function/rest-parameter-names.js b/js/src/tests/non262/Function/rest-parameter-names.js new file mode 100644 index 0000000000..6cfa01dcfb --- /dev/null +++ b/js/src/tests/non262/Function/rest-parameter-names.js @@ -0,0 +1,68 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 1288460; +var summary = + "Rest parameters to functions can be named |yield| or |eval| or |let| in " + "non-strict code"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var f1 = (...yield) => yield + 42; +assertEq(f1(), "42"); +assertEq(f1(1), "142"); + +var f2 = (...eval) => eval + 42; +assertEq(f2(), "42"); +assertEq(f2(1), "142"); + +var f3 = (...let) => let + 42; +assertEq(f3(), "42"); +assertEq(f3(1), "142"); + +function g1(x, ...yield) +{ + return yield + x; +} +assertEq(g1(0, 42), "420"); + +function g2(x, ...eval) +{ + return eval + x; +} +assertEq(g2(0, 42), "420"); + +function g3(x, ...let) +{ + return let + x; +} +assertEq(g3(0, 42), "420"); + +function h() +{ + "use strict"; + + var badNames = ["yield", "eval", "let"]; + + for (var badName of ["yield", "eval", "let"]) + { + assertThrowsInstanceOf(() => eval(`var q = (...${badName}) => ${badName} + 42;`), + SyntaxError); + + assertThrowsInstanceOf(() => eval(`function r(x, ...${badName}) { return x + ${badName}; }`), + SyntaxError); + } +} +h(); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Function/return-finally.js b/js/src/tests/non262/Function/return-finally.js new file mode 100644 index 0000000000..fe075d4576 --- /dev/null +++ b/js/src/tests/non262/Function/return-finally.js @@ -0,0 +1,172 @@ +var BUGNUMBER = 1202134; +var summary = "Return value should not be overwritten by finally block with normal execution."; + +print(BUGNUMBER + ": " + summary); + +// ==== single ==== + +var f; +f = function() { + // F.[[type]] is normal + // B.[[type]] is return + try { + return 42; + } finally { + } +}; +assertEq(f(), 42); + +f = function() { + // F.[[type]] is return + try { + return 42; + } finally { + return 43; + } +}; +assertEq(f(), 43); + +f = function() { + // F.[[type]] is throw + try { + return 42; + } finally { + throw 43; + } +}; +var caught = false; +try { + f(); +} catch (e) { + assertEq(e, 43); + caught = true; +} +assertEq(caught, true); + +f = function() { + // F.[[type]] is break + do try { + return 42; + } finally { + break; + } while (false); + return 43; +}; +assertEq(f(), 43); + +f = function() { + // F.[[type]] is break + L: try { + return 42; + } finally { + break L; + } + return 43; +}; +assertEq(f(), 43); + +f = function() { + // F.[[type]] is continue + do try { + return 42; + } finally { + continue; + } while (false); + return 43; +}; +assertEq(f(), 43); + +// ==== nested ==== + +f = function() { + // F.[[type]] is normal + // B.[[type]] is return + try { + return 42; + } finally { + // F.[[type]] is break + do try { + return 43; + } finally { + break; + } while (0); + } +}; +assertEq(f(), 42); + +f = function() { + // F.[[type]] is normal + // B.[[type]] is return + try { + return 42; + } finally { + // F.[[type]] is break + L: try { + return 43; + } finally { + break L; + } + } +} +assertEq(f(), 42); + +f = function() { + // F.[[type]] is normal + // B.[[type]] is return + try { + return 42; + } finally { + // F.[[type]] is continue + do try { + return 43; + } finally { + continue; + } while (0); + } +}; +assertEq(f(), 42); + +f = function() { + // F.[[type]] is normal + // B.[[type]] is return + try { + return 42; + } finally { + // F.[[type]] is normal + // B.[[type]] is normal + try { + // F.[[type]] is throw + try { + return 43; + } finally { + throw 9; + } + } catch (e) { + } + } +}; +assertEq(f(), 42); + +f = function() { + // F.[[type]] is return + try { + return 41; + } finally { + // F.[[type]] is normal + // B.[[type]] is return + try { + return 42; + } finally { + // F.[[type]] is break + do try { + return 43; + } finally { + break; + } while (0); + } + } +}; +assertEq(f(), 42); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Function/shell.js b/js/src/tests/non262/Function/shell.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Function/spread-iterator-primitive.js b/js/src/tests/non262/Function/spread-iterator-primitive.js new file mode 100644 index 0000000000..79320ad7f1 --- /dev/null +++ b/js/src/tests/non262/Function/spread-iterator-primitive.js @@ -0,0 +1,28 @@ +var BUGNUMBER = 1021835; +var summary = "Returning non-object from @@iterator should throw"; + +print(BUGNUMBER + ": " + summary); + +let primitives = [ + 1, + true, + undefined, + null, + "foo", + Symbol.iterator +]; + +function f() { +} + +for (let primitive of primitives) { + let arg = { + [Symbol.iterator]() { + return primitive; + } + }; + assertThrowsInstanceOf(() => f(...arg), TypeError); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Function/strict-arguments.js b/js/src/tests/non262/Function/strict-arguments.js new file mode 100644 index 0000000000..fce5f756c2 --- /dev/null +++ b/js/src/tests/non262/Function/strict-arguments.js @@ -0,0 +1,453 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = 'strict-arguments.js'; +var BUGNUMBER = 516255; +var summary = + "ES5 strict mode: arguments objects of strict mode functions must copy " + + "argument values"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function arrayEvery(arr, fun) +{ + return Array.prototype.every.call(arr, fun); +} + +function arraysEqual(a1, a2) +{ + return a1.length === a2.length && + arrayEvery(a1, function(v, i) { return v === a2[i]; }); +} + + +/************************ + * NON-STRICT ARGUMENTS * + ************************/ + +var obj = {}; + +function noargs() { return arguments; } + +assertEq(arraysEqual(noargs(), []), true); +assertEq(arraysEqual(noargs(1), [1]), true); +assertEq(arraysEqual(noargs(2, obj, 8), [2, obj, 8]), true); + +function args(a) { return arguments; } + +assertEq(arraysEqual(args(), []), true); +assertEq(arraysEqual(args(1), [1]), true); +assertEq(arraysEqual(args(1, obj), [1, obj]), true); +assertEq(arraysEqual(args("foopy"), ["foopy"]), true); + +function assign(a) +{ + a = 17; + return arguments; +} + +assertEq(arraysEqual(assign(1), [17]), true); + +function getLaterAssign(a) +{ + var o = arguments; + a = 17; + return o; +} + +assertEq(arraysEqual(getLaterAssign(1), [17]), true); + +function assignElementGetParameter(a) +{ + arguments[0] = 17; + return a; +} + +assertEq(assignElementGetParameter(42), 17); + +function assignParameterGetElement(a) +{ + a = 17; + return arguments[0]; +} + +assertEq(assignParameterGetElement(42), 17); + +function assignArgSub(x, y) +{ + arguments[0] = 3; + return arguments[0]; +} + +assertEq(assignArgSub(1), 3); + +function assignArgSubParamUse(x, y) +{ + arguments[0] = 3; + assertEq(x, 3); + return arguments[0]; +} + +assertEq(assignArgSubParamUse(1), 3); + +function assignArgumentsElement(x, y) +{ + arguments[0] = 3; + return arguments[Math.random() ? "0" : 0]; // nix arguments[const] optimizations +} + +assertEq(assignArgumentsElement(1), 3); + +function assignArgumentsElementParamUse(x, y) +{ + arguments[0] = 3; + assertEq(x, 3); + return arguments[Math.random() ? "0" : 0]; // nix arguments[const] optimizations +} + +assertEq(assignArgumentsElementParamUse(1), 3); + +/******************** + * STRICT ARGUMENTS * + ********************/ + +function strictNoargs() +{ + "use strict"; + return arguments; +} + +assertEq(arraysEqual(strictNoargs(), []), true); +assertEq(arraysEqual(strictNoargs(1), [1]), true); +assertEq(arraysEqual(strictNoargs(1, obj), [1, obj]), true); + +function strictArgs(a) +{ + "use strict"; + return arguments; +} + +assertEq(arraysEqual(strictArgs(), []), true); +assertEq(arraysEqual(strictArgs(1), [1]), true); +assertEq(arraysEqual(strictArgs(1, obj), [1, obj]), true); + +function strictAssign(a) +{ + "use strict"; + a = 17; + return arguments; +} + +assertEq(arraysEqual(strictAssign(), []), true); +assertEq(arraysEqual(strictAssign(1), [1]), true); +assertEq(arraysEqual(strictAssign(1, obj), [1, obj]), true); + +var upper; +function strictAssignAfter(a) +{ + "use strict"; + upper = arguments; + a = 42; + return upper; +} + +assertEq(arraysEqual(strictAssignAfter(), []), true); +assertEq(arraysEqual(strictAssignAfter(17), [17]), true); +assertEq(arraysEqual(strictAssignAfter(obj), [obj]), true); + +function strictMaybeAssignOuterParam(p) +{ + "use strict"; + function inner() { p = 17; } + return arguments; +} + +assertEq(arraysEqual(strictMaybeAssignOuterParam(), []), true); +assertEq(arraysEqual(strictMaybeAssignOuterParam(42), [42]), true); +assertEq(arraysEqual(strictMaybeAssignOuterParam(obj), [obj]), true); + +function strictAssignOuterParam(p) +{ + "use strict"; + function inner() { p = 17; } + inner(); + return arguments; +} + +assertEq(arraysEqual(strictAssignOuterParam(), []), true); +assertEq(arraysEqual(strictAssignOuterParam(17), [17]), true); +assertEq(arraysEqual(strictAssignOuterParam(obj), [obj]), true); + +function strictAssignOuterParamPSYCH(p) +{ + "use strict"; + function inner(p) { p = 17; } + inner(); + return arguments; +} + +assertEq(arraysEqual(strictAssignOuterParamPSYCH(), []), true); +assertEq(arraysEqual(strictAssignOuterParamPSYCH(17), [17]), true); +assertEq(arraysEqual(strictAssignOuterParamPSYCH(obj), [obj]), true); + +function strictEval(code, p) +{ + "use strict"; + eval(code); + return arguments; +} + +assertEq(arraysEqual(strictEval("1", 2), ["1", 2]), true); +assertEq(arraysEqual(strictEval("arguments"), ["arguments"]), true); +assertEq(arraysEqual(strictEval("p = 2"), ["p = 2"]), true); +assertEq(arraysEqual(strictEval("p = 2", 17), ["p = 2", 17]), true); +assertEq(arraysEqual(strictEval("arguments[0] = 17"), [17]), true); +assertEq(arraysEqual(strictEval("arguments[0] = 17", 42), [17, 42]), true); + +function strictMaybeNestedEval(code, p) +{ + "use strict"; + function inner() { eval(code); } + return arguments; +} + +assertEq(arraysEqual(strictMaybeNestedEval("1", 2), ["1", 2]), true); +assertEq(arraysEqual(strictMaybeNestedEval("arguments"), ["arguments"]), true); +assertEq(arraysEqual(strictMaybeNestedEval("p = 2"), ["p = 2"]), true); +assertEq(arraysEqual(strictMaybeNestedEval("p = 2", 17), ["p = 2", 17]), true); + +function strictNestedEval(code, p) +{ + "use strict"; + function inner() { eval(code); } + inner(); + return arguments; +} + +assertEq(arraysEqual(strictNestedEval("1", 2), ["1", 2]), true); +assertEq(arraysEqual(strictNestedEval("arguments"), ["arguments"]), true); +assertEq(arraysEqual(strictNestedEval("p = 2"), ["p = 2"]), true); +assertEq(arraysEqual(strictNestedEval("p = 2", 17), ["p = 2", 17]), true); +assertEq(arraysEqual(strictNestedEval("arguments[0] = 17"), ["arguments[0] = 17"]), true); +assertEq(arraysEqual(strictNestedEval("arguments[0] = 17", 42), ["arguments[0] = 17", 42]), true); + +function strictAssignArguments(a) +{ + "use strict"; + arguments[0] = 42; + return a; +} + +assertEq(strictAssignArguments(), undefined); +assertEq(strictAssignArguments(obj), obj); +assertEq(strictAssignArguments(17), 17); + +function strictAssignParameterGetElement(a) +{ + "use strict"; + a = 17; + return arguments[0]; +} + +assertEq(strictAssignParameterGetElement(42), 42); + +function strictAssignArgSub(x, y) +{ + "use strict"; + arguments[0] = 3; + return arguments[0]; +} + +assertEq(strictAssignArgSub(1), 3); + +function strictAssignArgSubParamUse(x, y) +{ + "use strict"; + arguments[0] = 3; + assertEq(x, 1); + return arguments[0]; +} + +assertEq(strictAssignArgSubParamUse(1), 3); + +function strictAssignArgumentsElement(x, y) +{ + "use strict"; + arguments[0] = 3; + return arguments[Math.random() ? "0" : 0]; // nix arguments[const] optimizations +} + +assertEq(strictAssignArgumentsElement(1), 3); + +function strictAssignArgumentsElementParamUse(x, y) +{ + "use strict"; + arguments[0] = 3; + assertEq(x, 1); + return arguments[Math.random() ? "0" : 0]; // nix arguments[const] optimizations +} + +assertEq(strictAssignArgumentsElementParamUse(1), 3); + +function strictNestedAssignShadowVar(p) +{ + "use strict"; + function inner() + { + var p = 12; + function innermost() { p = 1776; return 12; } + return innermost(); + } + return arguments; +} + +assertEq(arraysEqual(strictNestedAssignShadowVar(), []), true); +assertEq(arraysEqual(strictNestedAssignShadowVar(99), [99]), true); +assertEq(arraysEqual(strictNestedAssignShadowVar(""), [""]), true); +assertEq(arraysEqual(strictNestedAssignShadowVar(obj), [obj]), true); + +function strictNestedAssignShadowCatch(p) +{ + "use strict"; + function inner() + { + try + { + } + catch (p) + { + var f = function innermost() { p = 1776; return 12; }; + f(); + } + } + return arguments; +} + +assertEq(arraysEqual(strictNestedAssignShadowCatch(), []), true); +assertEq(arraysEqual(strictNestedAssignShadowCatch(99), [99]), true); +assertEq(arraysEqual(strictNestedAssignShadowCatch(""), [""]), true); +assertEq(arraysEqual(strictNestedAssignShadowCatch(obj), [obj]), true); + +function strictNestedAssignShadowCatchCall(p) +{ + "use strict"; + function inner() + { + try + { + } + catch (p) + { + var f = function innermost() { p = 1776; return 12; }; + f(); + } + } + inner(); + return arguments; +} + +assertEq(arraysEqual(strictNestedAssignShadowCatchCall(), []), true); +assertEq(arraysEqual(strictNestedAssignShadowCatchCall(99), [99]), true); +assertEq(arraysEqual(strictNestedAssignShadowCatchCall(""), [""]), true); +assertEq(arraysEqual(strictNestedAssignShadowCatchCall(obj), [obj]), true); + +function strictNestedAssignShadowFunction(p) +{ + "use strict"; + function inner() + { + function p() { } + p = 1776; + } + return arguments; +} + +assertEq(arraysEqual(strictNestedAssignShadowFunction(), []), true); +assertEq(arraysEqual(strictNestedAssignShadowFunction(99), [99]), true); +assertEq(arraysEqual(strictNestedAssignShadowFunction(""), [""]), true); +assertEq(arraysEqual(strictNestedAssignShadowFunction(obj), [obj]), true); + +function strictNestedAssignShadowFunctionCall(p) +{ + "use strict"; + function inner() + { + function p() { } + p = 1776; + } + return arguments; +} + +assertEq(arraysEqual(strictNestedAssignShadowFunctionCall(), []), true); +assertEq(arraysEqual(strictNestedAssignShadowFunctionCall(99), [99]), true); +assertEq(arraysEqual(strictNestedAssignShadowFunctionCall(""), [""]), true); +assertEq(arraysEqual(strictNestedAssignShadowFunctionCall(obj), [obj]), true); + +function strictNestedShadowAndMaybeEval(code, p) +{ + "use strict"; + function inner(p) { eval(code); } + return arguments; +} + +assertEq(arraysEqual(strictNestedShadowAndMaybeEval("1", 2), ["1", 2]), true); +assertEq(arraysEqual(strictNestedShadowAndMaybeEval("arguments"), ["arguments"]), true); +assertEq(arraysEqual(strictNestedShadowAndMaybeEval("p = 2"), ["p = 2"]), true); +assertEq(arraysEqual(strictNestedShadowAndMaybeEval("p = 2", 17), ["p = 2", 17]), true); +assertEq(arraysEqual(strictNestedShadowAndMaybeEval("arguments[0] = 17"), ["arguments[0] = 17"]), true); +assertEq(arraysEqual(strictNestedShadowAndMaybeEval("arguments[0] = 17", 42), ["arguments[0] = 17", 42]), true); + +function strictNestedShadowAndEval(code, p) +{ + "use strict"; + function inner(p) { eval(code); } + return arguments; +} + +assertEq(arraysEqual(strictNestedShadowAndEval("1", 2), ["1", 2]), true); +assertEq(arraysEqual(strictNestedShadowAndEval("arguments"), ["arguments"]), true); +assertEq(arraysEqual(strictNestedShadowAndEval("p = 2"), ["p = 2"]), true); +assertEq(arraysEqual(strictNestedShadowAndEval("p = 2", 17), ["p = 2", 17]), true); +assertEq(arraysEqual(strictNestedShadowAndEval("arguments[0] = 17"), ["arguments[0] = 17"]), true); +assertEq(arraysEqual(strictNestedShadowAndEval("arguments[0] = 17", 42), ["arguments[0] = 17", 42]), true); + +function strictEvalContainsMutation(code) +{ + "use strict"; + return eval(code); +} + +assertEq(arraysEqual(strictEvalContainsMutation("code = 17; arguments"), ["code = 17; arguments"]), true); +assertEq(arraysEqual(strictEvalContainsMutation("arguments[0] = 17; arguments"), [17]), true); +assertEq(strictEvalContainsMutation("arguments[0] = 17; code"), "arguments[0] = 17; code"); + +function strictNestedAssignShadowFunctionName(p) +{ + "use strict"; + function inner() + { + function p() { p = 1776; } + p(); + } + inner(); + return arguments; +} + +assertEq(arraysEqual(strictNestedAssignShadowFunctionName(), []), true); +assertEq(arraysEqual(strictNestedAssignShadowFunctionName(99), [99]), true); +assertEq(arraysEqual(strictNestedAssignShadowFunctionName(""), [""]), true); +assertEq(arraysEqual(strictNestedAssignShadowFunctionName(obj), [obj]), true); + + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Function/throw-type-error.js b/js/src/tests/non262/Function/throw-type-error.js new file mode 100644 index 0000000000..68dd6e1d07 --- /dev/null +++ b/js/src/tests/non262/Function/throw-type-error.js @@ -0,0 +1,16 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/publicdomain/zero/1.0/ + +const ThrowTypeError = function(){ + "use strict"; + return Object.getOwnPropertyDescriptor(arguments, "callee").get; +}(); + +assertDeepEq(Object.getOwnPropertyDescriptor(ThrowTypeError, "length"), { + value: 0, writable: false, enumerable: false, configurable: false +}); + +assertEq(Object.isFrozen(ThrowTypeError), true); + +if (typeof reportCompare == "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/GC/browser.js b/js/src/tests/non262/GC/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/GC/regress-104584.js b/js/src/tests/non262/GC/regress-104584.js new file mode 100644 index 0000000000..4148b69153 --- /dev/null +++ b/js/src/tests/non262/GC/regress-104584.js @@ -0,0 +1,46 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Date: 14 October 2001 + * + * SUMMARY: Regression test for Bugzilla bug 104584 + * See http://bugzilla.mozilla.org/show_bug.cgi?id=104584 + * + * Testing that we don't crash on this code. The idea is to + * call F,G WITHOUT providing an argument. This caused a crash + * on the second call to obj.toString() or print(obj) below - + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 104584; +var summary = "Testing that we don't crash on this code -"; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +F(); +G(); + +reportCompare('No Crash', 'No Crash', ''); + +function F(obj) +{ + if(!obj) + obj = {}; + obj.toString(); + gc(); + obj.toString(); +} + + +function G(obj) +{ + if(!obj) + obj = {}; + print(obj); + gc(); + print(obj); +} diff --git a/js/src/tests/non262/GC/regress-203278-2.js b/js/src/tests/non262/GC/regress-203278-2.js new file mode 100644 index 0000000000..5d3b4c99e0 --- /dev/null +++ b/js/src/tests/non262/GC/regress-203278-2.js @@ -0,0 +1,80 @@ +// |reftest| slow +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 203278; +var summary = 'Don\'t crash in recursive js_MarkGCThing'; +var actual = 'FAIL'; +var expect = 'PASS'; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +// Prepare array to test DeutschSchorrWaite implementation +// and its reverse pointer scanning performance + +var a = new Array(1000 * 1000); + +var i = a.length; +while (i-- != 0) { + switch (i % 11) { + case 0: + a[i] = { }; + break; + case 1: + a[i] = { a: true, b: false, c: 0 }; + break; + case 2: + a[i] = { 0: true, 1: {}, 2: false }; + break; + case 3: + a[i] = { a: 1.2, b: "", c: [] }; + break; + case 4: + a[i] = [ false ]; + break; + case 6: + a[i] = []; + break; + case 7: + a[i] = false; + break; + case 8: + a[i] = "x"; + break; + case 9: + a[i] = new String("x"); + break; + case 10: + a[i] = 1.1; + break; + case 10: + a[i] = new Boolean(); + break; + } +} + +printStatus("DSF is prepared"); + +// Prepare linked list that causes recursion during GC with +// depth O(list size) +// Note: pass "-S 500000" option to the shell to limit stack quota +// available for recursion + +for (i = 0; i != 50*1000; ++i) { + a = [a, a, {}]; + a = [a, {}, a]; + +} + +printStatus("Linked list is prepared"); + +gc(); + +actual = 'PASS'; + +reportCompare(expect, actual, summary); + diff --git a/js/src/tests/non262/GC/regress-203278-3.js b/js/src/tests/non262/GC/regress-203278-3.js new file mode 100644 index 0000000000..3ac6d4c91e --- /dev/null +++ b/js/src/tests/non262/GC/regress-203278-3.js @@ -0,0 +1,42 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 203278; +var summary = 'Don\'t crash in recursive js_MarkGCThing'; +var actual = 'FAIL'; +var expect = 'PASS'; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +// Prepare array a to cause O(a.length^2) behaviour in the current +// DeutschSchorrWaite implementation + +var a = new Array(1000 * 100); + +var i = a.length; +while (i-- != 0) +{ + a[i] = {}; +} + +// Prepare linked list that causes recursion during GC with +// depth O(list size) + +for (i = 0; i != 50*1000; ++i) +{ + a = [a, a.concat()]; +} + +if (typeof gc == 'function') +{ + gc(); +} + +actual = 'PASS'; + +reportCompare(expect, actual, summary); + diff --git a/js/src/tests/non262/GC/regress-278725.js b/js/src/tests/non262/GC/regress-278725.js new file mode 100644 index 0000000000..47df5950f0 --- /dev/null +++ b/js/src/tests/non262/GC/regress-278725.js @@ -0,0 +1,29 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +// testcase by James Ross +var BUGNUMBER = 278725; +var summary = 'Don\'t Crash during GC'; +var actual = 'Crash'; +var expect = 'No Crash'; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +var results = []; +for (var k = 0; k < 600000; k++) { + if (! (k %100000)) { + printStatus('hi'); + if (0) { + results.length = 0; + gc(); + } + } + results.push({}); +} + +actual = 'No Crash'; +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/GC/regress-306788.js b/js/src/tests/non262/GC/regress-306788.js new file mode 100644 index 0000000000..d6e1306795 --- /dev/null +++ b/js/src/tests/non262/GC/regress-306788.js @@ -0,0 +1,24 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 306788; +var summary = 'Do not crash sorting Arrays due to GC'; +var actual = 'No Crash'; +var expect = 'No Crash'; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +var array = new Array(); + +for (var i = 0; i < 5000; i++) +{ + array[i] = new Array('1', '2', '3', '4', '5'); +} + +array.sort(); + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/GC/regress-311497.js b/js/src/tests/non262/GC/regress-311497.js new file mode 100644 index 0000000000..21905a7fd8 --- /dev/null +++ b/js/src/tests/non262/GC/regress-311497.js @@ -0,0 +1,61 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 311497; +var summary = 'Root pivots in js_HeapSort'; +var actual = 'No Crash'; +var expect = 'No Crash'; + +printBugNumber(BUGNUMBER); +printStatus (summary); + + +function force_gc() +{ + if (this.gc) gc(); + for (var i = 0; i != 30000; ++i) { + var tmp = Math.sin(i); + tmp = null; + } +} + +var array = new Array(10); +for (var i = 0; i != array.length; ++i) { + array[i] = String.fromCharCode(i, i, i); +} + +function cmp(a, b) +{ + for (var i = 0; i != array.length; ++i) { + array[i] = null; + } + force_gc(); + return 0; +} + +array.sort(cmp); + +// Verify that array contains either null or original strings + +var null_count = 0; +var original_string_count = 0; +for (var i = 0; i != array.length; ++i) { + var elem = array[i]; + if (elem === null) { + ++null_count; + } else if (typeof elem == "string" && elem.length == 3) { + var code = elem.charCodeAt(0); + if (0 <= code && code < array.length) { + if (code === elem.charCodeAt(1) && code == elem.charCodeAt(2)) + ++original_string_count; + } + } +} + +var expect = array.length; +var actual = null_count + original_string_count; + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/GC/regress-313276.js b/js/src/tests/non262/GC/regress-313276.js new file mode 100644 index 0000000000..7f622fa3fe --- /dev/null +++ b/js/src/tests/non262/GC/regress-313276.js @@ -0,0 +1,40 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 313276; +var summary = 'Root strings'; +var actual = 'No Crash'; +var expect = 'No Crash'; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +var obj = { + toString: function() { + return "*TEST*".substr(1, 4); + } +}; + +var TMP = 1e200; + +var likeZero = { + valueOf: function() { + if (typeof gc == "function") gc(); + for (var i = 0; i != 40000; ++i) { + var tmp = 2 / TMP; + tmp = null; + } + return 0; + } +} + + expect = "TEST"; +actual = String.prototype.substr.call(obj, likeZero); + +printStatus("Substring length: "+actual.length); +printStatus((expect === actual).toString()); + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/GC/regress-313479.js b/js/src/tests/non262/GC/regress-313479.js new file mode 100644 index 0000000000..a13dba3ff6 --- /dev/null +++ b/js/src/tests/non262/GC/regress-313479.js @@ -0,0 +1,37 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 313479; +var summary = 'Root access in jsnum.c'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +var prepared_string = String(1); +String(2); // To remove prepared_string from newborn + +var likeString = { + toString: function() { + var tmp = prepared_string; + prepared_string = null; + return tmp; + } +}; + +var likeNumber = { + valueOf: function() { + gc(); + return 10; + } +} + + var expect = 1; +var actual = parseInt(likeString, likeNumber); +printStatus("expect="+expect+" actual="+actual); + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/GC/regress-316885-01.js b/js/src/tests/non262/GC/regress-316885-01.js new file mode 100644 index 0000000000..da814bbae4 --- /dev/null +++ b/js/src/tests/non262/GC/regress-316885-01.js @@ -0,0 +1,33 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 316885; +var summary = 'Unrooted access in jsinterp.c'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +var str_with_num = "0.1"; + +var obj = { + get elem() { + return str_with_num; + }, + set elem(value) { + gc(); + } + +}; + +expect = Number(str_with_num); +actual = obj.elem++; + +gc(); + + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/GC/regress-316885-02.js b/js/src/tests/non262/GC/regress-316885-02.js new file mode 100644 index 0000000000..2cdda60065 --- /dev/null +++ b/js/src/tests/non262/GC/regress-316885-02.js @@ -0,0 +1,42 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 316885; +var summary = 'Unrooted access in jsinterp.c'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +var str = "test"; + +var lval = { + valueOf: function() { + return str+"1"; + } +}; + +var ONE = 1; + +var rval = { + valueOf: function() { + // Make sure that the result of the previous lval.valueOf + // is not GC-rooted. + var tmp = "x"+lval; + if (typeof gc == "function") + gc(); + for (var i = 0; i != 40000; ++i) { + tmp = 1e100 / ONE; + } + return str; + } +}; + +expect = (str+"1" > str); +actual = (lval > rval); + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/GC/regress-316885-03.js b/js/src/tests/non262/GC/regress-316885-03.js new file mode 100644 index 0000000000..93f632e783 --- /dev/null +++ b/js/src/tests/non262/GC/regress-316885-03.js @@ -0,0 +1,42 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 316885; +var summary = 'Unrooted access in jsinterp.c'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +var str = "test"; + +var lval = { + valueOf: function() { + return str+"1"; + } +}; + +var ONE = 1; + +var rval = { + valueOf: function() { + // Make sure that the result of the previous lval.valueOf + // is not GC-rooted. + var tmp = "x"+lval; + if (typeof gc == "function") + gc(); + for (var i = 0; i != 40000; ++i) { + tmp = 1e100 / ONE; + } + return str; + } +}; + +expect = (str+"1")+str; +actual = lval+rval; + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/GC/regress-319980-01.js b/js/src/tests/non262/GC/regress-319980-01.js new file mode 100644 index 0000000000..7c49b54bb8 --- /dev/null +++ b/js/src/tests/non262/GC/regress-319980-01.js @@ -0,0 +1,117 @@ +// |reftest| skip slow +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 319980; +var summary = 'GC not called during non-fatal out of memory'; +var actual = ''; +var expect = 'Normal Exit'; + +printBugNumber(BUGNUMBER); +printStatus (summary); +print ('This test should never fail explicitly. ' + + 'You must view the memory usage during the test. ' + + 'This test fails if memory usage for each subtest grows'); + +var timeOut = 45 * 1000; +var interval = 0.01 * 1000; +var testFuncWatcherId; +var testFuncTimerId; +var maxTests = 5; +var currTest = 0; + +// delay start until after js-test-driver-end runs. +// delay test driver end +gDelayTestDriverEnd = true; + +setTimeout(testFuncWatcher, 1000); + +function testFuncWatcher() +{ + a = null; + + gc(); + + clearTimeout(testFuncTimerId); + testFuncWatcherId = testFuncTimerId = null; + if (currTest >= maxTests) + { + actual = 'Normal Exit'; + reportCompare(expect, actual, summary); + printStatus('Test Completed'); + gDelayTestDriverEnd = false; + jsTestDriverEnd(); + return; + } + ++currTest; + + print('Executing test ' + currTest + '\n'); + + testFuncWatcherId = setTimeout("testFuncWatcher()", timeOut); + testFuncTimerId = setTimeout(testFunc, interval); +} + + +var a; +function testFunc() +{ + + var i; + + switch(currTest) + { + case 1: + a = new Array(100000); + for (i = 0; i < 100000; i++ ) + { + a[i] = i; + } + break; + + case 2: + a = new Array(100000); + for (i = 0; i < 100000; i++) + { + a[i] = new Number(); + a[i] = i; + } + break; + + case 3: + a = new String() ; + a = new Array(100000); + for ( i = 0; i < 100000; i++ ) + { + a[i] = i; + } + + break; + + case 4: + a = new Array(); + a[0] = new Array(100000); + for (i = 0; i < 100000; i++ ) + { + a[0][i] = i; + } + break; + + case 5: + a = new Array(); + for (i = 0; i < 100000; i++ ) + { + a[i] = i; + } + break; + } + + if (testFuncTimerId) + { + testFuncTimerId = setTimeout(testFunc, interval); + } +} + + diff --git a/js/src/tests/non262/GC/regress-324278.js b/js/src/tests/non262/GC/regress-324278.js new file mode 100644 index 0000000000..56996994d2 --- /dev/null +++ b/js/src/tests/non262/GC/regress-324278.js @@ -0,0 +1,63 @@ +// |reftest| skip -- slow, obsoleted by 98409 fix +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 324278; +var summary = 'GC without recursion'; +var actual = 'No Crash'; +var expect = 'No Crash'; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +// Number to push native stack size beyond 10MB if GC recurses generating +// segfault on Fedora Core / Ubuntu Linuxes where the stack size by default +// is 10MB/8MB. +var N = 100*1000; + +function build(N) { + // Exploit the fact that (in ES3), regexp literals are shared between + // function invocations. Thus we build the following chain: + // chainTop: function->regexp->function->regexp....->null + // to check how GC would deal with this chain. + + var chainTop = null; + for (var i = 0; i != N; ++i) { + var f = Function('some_arg'+i, ' return /test/;'); + var re = f(); + re.previous = chainTop; + chainTop = f; + } + return chainTop; +} + +function check(chainTop, N) { + for (var i = 0; i != N; ++i) { + var re = chainTop(); + chainTop = re.previous; + } + if (chainTop !== null) + throw "Bad chainTop"; + +} + +if (typeof gc != "function") { + gc = function() { + for (var i = 0; i != 50*1000; ++i) { + var tmp = new Object(); + } + } +} + +var chainTop = build(N); +printStatus("BUILT"); +gc(); +check(chainTop, N); +printStatus("CHECKED"); +chainTop = null; +gc(); + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/GC/regress-331719.js b/js/src/tests/non262/GC/regress-331719.js new file mode 100644 index 0000000000..3803b3d5cb --- /dev/null +++ b/js/src/tests/non262/GC/regress-331719.js @@ -0,0 +1,19 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 331719; +var summary = 'Problem with String.replace running with WAY_TOO_MUCH_GC'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); +print('This test requires WAY_TOO_MUCH_GC'); + +expect = 'No'; +actual = 'No'.replace(/\&\&/g, '&'); + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/GC/regress-338653.js b/js/src/tests/non262/GC/regress-338653.js new file mode 100644 index 0000000000..da1b7c5059 --- /dev/null +++ b/js/src/tests/non262/GC/regress-338653.js @@ -0,0 +1,41 @@ +// |reftest| slow +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 338653; +var summary = 'Force GC when JSRuntime.gcMallocBytes hits ' + + 'JSRuntime.gcMaxMallocBytes'; +var actual = 'No Crash'; +var expect = 'No Crash'; + +printBugNumber(BUGNUMBER); +printStatus (summary); +print('This test should never fail explicitly. ' + + 'You must view the memory usage during the test. ' + + 'This test fails if the memory usage repeatedly spikes ' + + 'by several hundred megabytes.'); + +function dosubst() +{ + var f = '0x'; + var s = f; + + for (var i = 0; i < 18; i++) + { + s += s; + } + + var index = s.indexOf(f); + while (index != -1 && index < 10000) { + s = s.substr(0, index) + '1' + s.substr(index + f.length); + index = s.indexOf(f); + } + +} + +dosubst(); + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/GC/regress-341877-01.js b/js/src/tests/non262/GC/regress-341877-01.js new file mode 100644 index 0000000000..6fc88f3ac0 --- /dev/null +++ b/js/src/tests/non262/GC/regress-341877-01.js @@ -0,0 +1,40 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 341877; +var summary = 'GC hazard with for-in loop'; +var actual = 'No Crash'; +var expect = 'No Crash'; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +var obj = { }; + +var prop = "xsomePropety".substr(1); + +obj.first = "first" + + obj[prop] = 1; + +for (var elem in obj) { + var tmp = elem.toString(); + delete obj[prop]; + // ensure that prop is cut from all roots + prop = "xsomePropety".substr(2); + obj[prop] = 2; + delete obj[prop]; + prop = null; + if (typeof gc == 'function') + gc(); + for (var i = 0; i != 50000; ++i) { + var tmp = 1 / 3; + tmp /= 10; + } +} + + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/GC/regress-341877-02.js b/js/src/tests/non262/GC/regress-341877-02.js new file mode 100644 index 0000000000..b636ad6930 --- /dev/null +++ b/js/src/tests/non262/GC/regress-341877-02.js @@ -0,0 +1,45 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 341877; +var summary = 'GC hazard with for-in loop'; +var actual = 'No Crash'; +var expect = 'No Crash'; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +var obj = { }; + +var prop = "xsomePropety".substr(1); + +obj.first = "first" + + obj[prop] = 1; + +for (var elem in obj) { + var tmp = elem.toString(); + delete obj[prop]; + // ensure that prop is cut from all roots + prop = "xsomePropety".substr(2); + obj[prop] = 2; + delete obj[prop]; + prop = null; + if (typeof gc == 'function') + gc(); + for (var i = 0; i != 50000; ++i) { + var tmp = 1 / 3; + tmp /= 10; + } + for (var i = 0; i != 1000; ++i) { + // Make string with 11 characters that would take + // (11 + 1) * 2 bytes or sizeof(JSAtom) so eventually + // malloc will ovewrite just freed atoms. + var tmp2 = Array(12).join(' '); + } +} + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/GC/regress-348532.js b/js/src/tests/non262/GC/regress-348532.js new file mode 100644 index 0000000000..24f5624143 --- /dev/null +++ b/js/src/tests/non262/GC/regress-348532.js @@ -0,0 +1,51 @@ +// |reftest| slow skip-if(Android) +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 348532; +var summary = 'Do not overflow int when constructing Error.stack'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + expectExitCode(0); + expectExitCode(3); + actual = 0; + + // construct string of 1<<23 characters + var s = Array((1<<23)+1).join('x'); + + var recursionDepth = 0; + function err() { + try { + return err.apply(this, arguments); + } catch (e) { + if (!(e instanceof InternalError)) + throw e; + } + return new Error(); + } + + // The full stack trace in error would include 64*4 copies of s exceeding + // 2^23 * 256 or 2^31 in length + var error = err(s,s,s,s); + + print(error.stack.length); + + expect = true; + actual = (error.stack.length > 0); + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/GC/regress-352606.js b/js/src/tests/non262/GC/regress-352606.js new file mode 100644 index 0000000000..61ad848f8b --- /dev/null +++ b/js/src/tests/non262/GC/regress-352606.js @@ -0,0 +1,25 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 352606; +var summary = 'Do not crash involving post decrement'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + y = ({toString: gc}); new Function("y--;")() + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/GC/regress-383269-01.js b/js/src/tests/non262/GC/regress-383269-01.js new file mode 100644 index 0000000000..6802e1460f --- /dev/null +++ b/js/src/tests/non262/GC/regress-383269-01.js @@ -0,0 +1,59 @@ +// |reftest| random -- unreliable - based on GC timing +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 383269; +var summary = 'Leak related to arguments object'; +var actual = 'No Leak'; +var expect = 'No Leak'; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + function generate_big_object_graph() + { + var root = {}; + f(root, 17); + return root; + function f(parent, depth) { + if (depth == 0) + return; + --depth; + f(parent.a = {}, depth); + f(parent.b = {}, depth); + } + } + + function outer() { var x = arguments; return function inner() { return x }; } + + function timed_gc() + { + var t1 = Date.now(); + gc(); + return Date.now() - t1; + } + + outer(1); + gc(); + var base_time = timed_gc(); + + var f = outer(generate_big_object_graph()); + f = null; + gc(); + var time = timed_gc(); + + if (time > (base_time + 1) * 3) + actual = "generate_big_object_graph() leaked, base_gc_time="+base_time+", last_gc_time="+time; + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/GC/regress-383269-02.js b/js/src/tests/non262/GC/regress-383269-02.js new file mode 100644 index 0000000000..67c31bfc0e --- /dev/null +++ b/js/src/tests/non262/GC/regress-383269-02.js @@ -0,0 +1,63 @@ +// |reftest| random -- unreliable - based on GC timing +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 383269; +var summary = 'Leak related to arguments object'; +var actual = 'No Leak'; +var expect = 'No Leak'; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + function generate_big_object_graph() + { + var root = {}; + f(root, 17); + return root; + function f(parent, depth) { + if (depth == 0) + return; + --depth; + f(parent.a = {}, depth); + f(parent.b = {}, depth); + } + } + + function f(obj) { + with (obj) + return arguments; + } + + function timed_gc() + { + var t1 = Date.now(); + gc(); + return Date.now() - t1; + } + + var x = f({}); + x = null; + gc(); + var base_time = timed_gc(); + + x = f(generate_big_object_graph()); + x = null; + gc(); + var time = timed_gc(); + + if (time > (base_time + 10) * 3) + actual = "generate_big_object_graph() leaked, base_gc_time="+base_time+", last_gc_time="+time; + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/GC/regress-390078.js b/js/src/tests/non262/GC/regress-390078.js new file mode 100644 index 0000000000..251fdc82e2 --- /dev/null +++ b/js/src/tests/non262/GC/regress-390078.js @@ -0,0 +1,33 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +//----------------------------------------------------------------------------- +var BUGNUMBER = 390078; +var summary = 'GC hazard with JSstackFrame.argv[-1]'; +var actual = 'No Crash'; +var expect = 'No Crash'; + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + var a = new Array(10*1000); + a[0] = { toString: function() { gc(); return ".*9"; }};; + a[1] = "g"; + + for (var i = 0; i != 10*1000; ++i) { + String(new Number(123456789)); + } + + "".match.apply(123456789, a); + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/GC/regress-418128.js b/js/src/tests/non262/GC/regress-418128.js new file mode 100644 index 0000000000..77f9b2c78c --- /dev/null +++ b/js/src/tests/non262/GC/regress-418128.js @@ -0,0 +1,36 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 418128; +var summary = 'GC hazard with ++/--'; +var actual = 'No Crash'; +var expect = 'No Crash'; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + var obj = {}; + var id = { toString: function() { return ""+Math.pow(2, 0.1); } } + obj[id] = { valueOf: unrooter }; + print(obj[id]++); + gc(); + + function unrooter() + { + delete obj[id]; + gc(); + return 10; + } + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/GC/regress-440558.js b/js/src/tests/non262/GC/regress-440558.js new file mode 100644 index 0000000000..3daef0f146 --- /dev/null +++ b/js/src/tests/non262/GC/regress-440558.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(Android) +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 440558; +var summary = 'Do not assert: *flagp != GCF_FINAL'; +var actual = 'No Crash'; +var expect = 'No Crash'; + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + print('Note: this test requires that javascript.options.gczeal ' + + 'be set to 2 prior to the browser start'); + + m = function(a, b) { + if (++i < 10) { + } + }; + e = function(a, b) { + }; + + reportCompare(expect, actual, summary); +} + diff --git a/js/src/tests/non262/GC/shell.js b/js/src/tests/non262/GC/shell.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Intl/Array/shell.js b/js/src/tests/non262/Intl/Array/shell.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Intl/Array/toLocaleString-date.js b/js/src/tests/non262/Intl/Array/toLocaleString-date.js new file mode 100644 index 0000000000..7711c60643 --- /dev/null +++ b/js/src/tests/non262/Intl/Array/toLocaleString-date.js @@ -0,0 +1,53 @@ +if (typeof Intl === "object") { + const localeSep = [,,].toLocaleString(); + + const date = new Date(Date.UTC(2012, 11, 12, 3, 0, 0)); + + assertEq([date].toLocaleString("en-us", {timeZone: "UTC"}), "12/12/2012, 3:00:00 AM"); + assertEq([date].toLocaleString(["de", "en"], {timeZone: "UTC"}), "12.12.2012, 03:00:00"); + assertEq([date].toLocaleString("th-th", {timeZone: "UTC"}), "12/12/2555 03:00:00"); + assertEq([date].toLocaleString("th-th-u-nu-thai", {timeZone: "UTC"}), "๑๒/๑๒/๒๕๕๕ ๐๓:๐๐:๐๐"); + + const sampleValues = [ + date, new Date(0), + ]; + const sampleLocales = [ + void 0, + "en", + "th-th-u-nu-thai", + "ja-jp", + "ar-ma-u-ca-islamicc", + ["tlh", "de"], + ]; + const numericFormatOptions = { + timeZone: "UTC", + year: "numeric", month: "numeric", day: "numeric", + hour: "numeric", minute: "numeric", second: "numeric", + }; + const longFormatOptions = { + timeZone: "UTC", + year: "numeric", month: "long", day: "numeric", + hour: "numeric", minute: "numeric", second: "numeric" + }; + const sampleOptions = [ + {timeZone: "UTC"}, + longFormatOptions, + ]; + + for (let locale of sampleLocales) { + for (let options of sampleOptions) { + let dtfOptions; + if (options === longFormatOptions) { + dtfOptions = longFormatOptions; + } else { + dtfOptions = numericFormatOptions; + } + let dtf = new Intl.DateTimeFormat(locale, dtfOptions); + let expected = sampleValues.map(dtf.format).join(localeSep); + assertEq(sampleValues.toLocaleString(locale, options), expected); + } + } +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/Array/toLocaleString-number.js b/js/src/tests/non262/Intl/Array/toLocaleString-number.js new file mode 100644 index 0000000000..6ca8a17837 --- /dev/null +++ b/js/src/tests/non262/Intl/Array/toLocaleString-number.js @@ -0,0 +1,34 @@ +if (typeof Intl === "object") { + const localeSep = [,,].toLocaleString(); + + assertEq([NaN].toLocaleString("ar"), "ليس رقم"); + assertEq([NaN].toLocaleString(["zh-hant", "ar"]), "非數值"); + assertEq([Infinity].toLocaleString("dz"), "གྲངས་མེད"); + assertEq([-Infinity].toLocaleString(["fr", "en"]), "-∞"); + + const sampleValues = [ + -0, +0, -1, +1, -2, +2, -0.5, +0.5, + ]; + const sampleLocales = [ + void 0, + "en", + "th-th-u-nu-thai", + ["tlh", "de"], + ]; + const sampleOptions = [ + void 0, + {}, + {style: "percent"}, + {style: "currency", currency: "USD", minimumIntegerDigits: 4}, + ]; + for (let locale of sampleLocales) { + for (let options of sampleOptions) { + let nf = new Intl.NumberFormat(locale, options); + let expected = sampleValues.map(nf.format).join(localeSep); + assertEq(sampleValues.toLocaleString(locale, options), expected); + } + } +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/Array/toLocaleString.js b/js/src/tests/non262/Intl/Array/toLocaleString.js new file mode 100644 index 0000000000..f94e531f89 --- /dev/null +++ b/js/src/tests/non262/Intl/Array/toLocaleString.js @@ -0,0 +1,35 @@ +if (typeof Intl === "object") { + const localeSep = [,,].toLocaleString(); + + // Missing arguments are passed as |undefined|. + const objNoArgs = { + toLocaleString() { + assertEq(arguments.length, 2); + assertEq(arguments[0], undefined); + assertEq(arguments[1], undefined); + return "pass"; + } + }; + // - Single element case. + assertEq([objNoArgs].toLocaleString(), "pass"); + // - More than one element. + assertEq([objNoArgs, objNoArgs].toLocaleString(), "pass" + localeSep + "pass"); + + // Ensure "locales" and "options" arguments are passed to the array elements. + const locales = {}, options = {}; + const objWithArgs = { + toLocaleString() { + assertEq(arguments.length, 2); + assertEq(arguments[0], locales); + assertEq(arguments[1], options); + return "pass"; + } + }; + // - Single element case. + assertEq([objWithArgs].toLocaleString(locales, options), "pass"); + // - More than one element. + assertEq([objWithArgs, objWithArgs].toLocaleString(locales, options), "pass" + localeSep + "pass"); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/Collator/big5han-gb2312han.js b/js/src/tests/non262/Intl/Collator/big5han-gb2312han.js new file mode 100644 index 0000000000..cf6870ff7d --- /dev/null +++ b/js/src/tests/non262/Intl/Collator/big5han-gb2312han.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +let scrambled = ['𠙶', '𠇲', '㓙', '㑧', '假', '凷']; + +// Root or pinyin +const fallback = ["假", "凷", "㑧", "㓙", "𠇲", "𠙶"]; + +scrambled.sort(new Intl.Collator("zh-u-co-big5han").compare); +assertEqArray(scrambled, fallback); + +scrambled.sort(new Intl.Collator("zh-u-co-gb2312").compare); +assertEqArray(scrambled, fallback); + +assertEq(new Intl.Collator("zh-u-co-big5han").resolvedOptions().collation, "default"); +assertEq(new Intl.Collator("zh-u-co-gb2312").resolvedOptions().collation, "default"); + +assertEq(Intl.supportedValuesOf("collation").includes("big5han"), false); +assertEq(Intl.supportedValuesOf("collation").includes("gb2312"), false); + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Intl/Collator/browser.js b/js/src/tests/non262/Intl/Collator/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Intl/Collator/call.js b/js/src/tests/non262/Intl/Collator/call.js new file mode 100644 index 0000000000..089764a2cb --- /dev/null +++ b/js/src/tests/non262/Intl/Collator/call.js @@ -0,0 +1,74 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +function IsIntlService(c) { + return typeof c === "function" && + c.hasOwnProperty("prototype") && + c.prototype.hasOwnProperty("resolvedOptions"); +} + +function IsObject(o) { + return Object(o) === o; +} + +function thisValues() { + const intlConstructors = Object.getOwnPropertyNames(Intl).map(name => Intl[name]).filter(IsIntlService); + + return [ + // Primitive values. + ...[undefined, null, true, "abc", Symbol(), 123], + + // Object values. + ...[{}, [], /(?:)/, function(){}, new Proxy({}, {})], + + // Intl objects. + ...[].concat(...intlConstructors.map(ctor => { + let args = []; + if (ctor === Intl.DisplayNames) { + // Intl.DisplayNames can't be constructed without any arguments. + args = [undefined, {type: "language"}]; + } + + return [ + // Instance of an Intl constructor. + new ctor(...args), + + // Instance of a subclassed Intl constructor. + new class extends ctor {}(...args), + + // Object inheriting from an Intl constructor prototype. + Object.create(ctor.prototype), + + // Intl object not inheriting from its default prototype. + Object.setPrototypeOf(new ctor(...args), Object.prototype), + ]; + })), + ]; +} + +// Invoking [[Call]] for Intl.Collator always returns a new Collator instance. +for (let thisValue of thisValues()) { + let obj = Intl.Collator.call(thisValue); + assertEq(Object.is(obj, thisValue), false); + assertEq(obj instanceof Intl.Collator, true); + + // Ensure Intl.[[FallbackSymbol]] wasn't installed on |thisValue|. + if (IsObject(thisValue)) + assertEqArray(Object.getOwnPropertySymbols(thisValue), []); +} + +// Intl.Collator doesn't use the legacy Intl constructor compromise semantics. +for (let thisValue of thisValues()) { + // Ensure instanceof operator isn't invoked for Intl.Collator. + Object.defineProperty(Intl.Collator, Symbol.hasInstance, { + get() { + assertEq(false, true, "@@hasInstance operator called"); + }, configurable: true + }); + let obj = Intl.Collator.call(thisValue); + delete Intl.Collator[Symbol.hasInstance]; + assertEq(Object.is(obj, thisValue), false); + assertEq(obj instanceof Intl.Collator, true); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/Collator/caseFirst.js b/js/src/tests/non262/Intl/Collator/caseFirst.js new file mode 100644 index 0000000000..d183c8fdd5 --- /dev/null +++ b/js/src/tests/non262/Intl/Collator/caseFirst.js @@ -0,0 +1,197 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Locales which use caseFirst=off for the standard (sort) collation type. +const defaultLocales = Intl.Collator.supportedLocalesOf(["en", "de", "es", "sv", "ar", "zh", "ja"]); + +// Locales which use caseFirst=upper for the standard (sort) collation type. +const upperFirstLocales = Intl.Collator.supportedLocalesOf(["cu", "da", "mt"]); + +// Default collation for zh (pinyin) reorders "á" before "a" at secondary strength level. +const accentReordered = ["zh"]; + +const allLocales = [...defaultLocales, ...upperFirstLocales]; + + +// Check default "caseFirst" option is resolved correctly. +for (let locale of defaultLocales) { + let col = new Intl.Collator(locale, {usage: "sort"}); + assertEq(col.resolvedOptions().caseFirst, "false"); +} +for (let locale of upperFirstLocales) { + let col = new Intl.Collator(locale, {usage: "sort"}); + assertEq(col.resolvedOptions().caseFirst, "upper"); +} +for (let locale of allLocales) { + let col = new Intl.Collator(locale, {usage: "search"}); + assertEq(col.resolvedOptions().caseFirst, "false"); +} + + +const collOptions = {usage: "sort"}; +const primary = {sensitivity: "base"}; +const secondary = {sensitivity: "accent"}; +const tertiary = {sensitivity: "variant"}; +const caseLevel = {sensitivity: "case"}; +const strengths = [primary, secondary, tertiary, caseLevel]; + +// "A" is sorted after "a" when caseFirst=off is the default and strength is tertiary. +for (let locale of defaultLocales) { + let col = new Intl.Collator(locale, Object.assign({}, collOptions, tertiary)); + + assertEq(col.compare("A", "a"), 1); + assertEq(col.compare("a", "A"), -1); +} +for (let locale of defaultLocales.filter(loc => !accentReordered.includes(loc))) { + let col = new Intl.Collator(locale, Object.assign({}, collOptions, tertiary)); + + assertEq(col.compare("A", "á"), -1); + assertEq(col.compare("á", "A"), 1); +} + +// Also sorted after "a" with the sensitivity=case collator. +for (let locale of defaultLocales) { + let col = new Intl.Collator(locale, Object.assign({}, collOptions, caseLevel)); + + assertEq(col.compare("A", "a"), 1); + assertEq(col.compare("a", "A"), -1); + + assertEq(col.compare("A", "á"), 1); + assertEq(col.compare("á", "A"), -1); +} + + +// "A" is sorted before "a" when caseFirst=upper is the default and strength is tertiary. +for (let locale of upperFirstLocales) { + let col = new Intl.Collator(locale, Object.assign({}, collOptions, tertiary)); + + assertEq(col.compare("A", "a"), -1); + assertEq(col.compare("a", "A"), 1); + + assertEq(col.compare("A", "á"), -1); + assertEq(col.compare("á", "A"), 1); +} + +// Also sorted before "a" with the sensitivity=case collator. +for (let locale of upperFirstLocales) { + let col = new Intl.Collator(locale, Object.assign({}, collOptions, caseLevel)); + + assertEq(col.compare("A", "a"), -1); + assertEq(col.compare("a", "A"), 1); + + assertEq(col.compare("A", "á"), -1); + assertEq(col.compare("á", "A"), 1); +} + + +// caseFirst=upper doesn't change the sort order when strength is below tertiary. +for (let locale of allLocales) { + let col = new Intl.Collator(locale, Object.assign({}, collOptions, secondary)); + + assertEq(col.compare("A", "a"), 0); + assertEq(col.compare("a", "A"), 0); +} +for (let locale of allLocales.filter(loc => !accentReordered.includes(loc))) { + let col = new Intl.Collator(locale, Object.assign({}, collOptions, secondary)); + + assertEq(col.compare("A", "á"), -1); + assertEq(col.compare("á", "A"), 1); +} + +for (let locale of allLocales) { + let col = new Intl.Collator(locale, Object.assign({}, collOptions, primary)); + + assertEq(col.compare("A", "a"), 0); + assertEq(col.compare("a", "A"), 0); + + assertEq(col.compare("A", "á"), 0); + assertEq(col.compare("á", "A"), 0); +} + + +// caseFirst=upper doesn't change the sort order when there's a primary difference. +for (let locale of allLocales) { + for (let strength of strengths) { + let col = new Intl.Collator(locale, Object.assign({}, collOptions, strength)); + + assertEq(col.compare("A", "b"), -1); + assertEq(col.compare("a", "B"), -1); + } +} + + +// caseFirst set through Unicode extension tag. +for (let locale of allLocales) { + let colKfFalse = new Intl.Collator(locale + "-u-kf-false", {}); + let colKfLower = new Intl.Collator(locale + "-u-kf-lower", {}); + let colKfUpper = new Intl.Collator(locale + "-u-kf-upper", {}); + + assertEq(colKfFalse.resolvedOptions().caseFirst, "false"); + assertEq(colKfFalse.compare("A", "a"), 1); + assertEq(colKfFalse.compare("a", "A"), -1); + + assertEq(colKfLower.resolvedOptions().caseFirst, "lower"); + assertEq(colKfLower.compare("A", "a"), 1); + assertEq(colKfLower.compare("a", "A"), -1); + + assertEq(colKfUpper.resolvedOptions().caseFirst, "upper"); + assertEq(colKfUpper.compare("A", "a"), -1); + assertEq(colKfUpper.compare("a", "A"), 1); +} + + +// caseFirst set through options value. +for (let locale of allLocales) { + let colKfFalse = new Intl.Collator(locale, {caseFirst: "false"}); + let colKfLower = new Intl.Collator(locale, {caseFirst: "lower"}); + let colKfUpper = new Intl.Collator(locale, {caseFirst: "upper"}); + + assertEq(colKfFalse.resolvedOptions().caseFirst, "false"); + assertEq(colKfFalse.compare("A", "a"), 1); + assertEq(colKfFalse.compare("a", "A"), -1); + + assertEq(colKfLower.resolvedOptions().caseFirst, "lower"); + assertEq(colKfLower.compare("A", "a"), 1); + assertEq(colKfLower.compare("a", "A"), -1); + + assertEq(colKfUpper.resolvedOptions().caseFirst, "upper"); + assertEq(colKfUpper.compare("A", "a"), -1); + assertEq(colKfUpper.compare("a", "A"), 1); +} + + +// Test Unicode extension tag and options value, the latter should win. +for (let locale of allLocales) { + let colKfFalse = new Intl.Collator(locale + "-u-kf-upper", {caseFirst: "false"}); + let colKfLower = new Intl.Collator(locale + "-u-kf-upper", {caseFirst: "lower"}); + let colKfUpper = new Intl.Collator(locale + "-u-kf-lower", {caseFirst: "upper"}); + + assertEq(colKfFalse.resolvedOptions().caseFirst, "false"); + assertEq(colKfFalse.compare("A", "a"), 1); + assertEq(colKfFalse.compare("a", "A"), -1); + + assertEq(colKfLower.resolvedOptions().caseFirst, "lower"); + assertEq(colKfLower.compare("A", "a"), 1); + assertEq(colKfLower.compare("a", "A"), -1); + + assertEq(colKfUpper.resolvedOptions().caseFirst, "upper"); + assertEq(colKfUpper.compare("A", "a"), -1); + assertEq(colKfUpper.compare("a", "A"), 1); +} + +// Ensure languages are properly detected when additional subtags are present. +if (Intl.Collator.supportedLocalesOf("da").length !== 0) { + assertEq(new Intl.Collator("da-DK", {usage: "sort"}).resolvedOptions().caseFirst, "upper"); + assertEq(new Intl.Collator("da-Latn-DK", {usage: "sort"}).resolvedOptions().caseFirst, "upper"); +} +if (Intl.Collator.supportedLocalesOf("mt").length !== 0) { + assertEq(new Intl.Collator("mt-MT", {usage: "sort"}).resolvedOptions().caseFirst, "upper"); + assertEq(new Intl.Collator("mt-Latn-MT", {usage: "sort"}).resolvedOptions().caseFirst, "upper"); +} + + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/Collator/collation.js b/js/src/tests/non262/Intl/Collator/collation.js new file mode 100644 index 0000000000..f73728b876 --- /dev/null +++ b/js/src/tests/non262/Intl/Collator/collation.js @@ -0,0 +1,90 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Collation can be set as Unicode locale extension or as a property. +{ + let c1 = new Intl.Collator("de", {usage: "sort"}); + let c2 = new Intl.Collator("de", {usage: "sort", collation: "phonebk"}); + let c3 = new Intl.Collator("de-u-co-phonebk", {usage: "sort"}); + + assertEq(c1.resolvedOptions().locale, "de"); + assertEq(c2.resolvedOptions().locale, "de"); + assertEq(c3.resolvedOptions().locale, "de-u-co-phonebk"); + + assertEq(c1.resolvedOptions().collation, "default"); + assertEq(c2.resolvedOptions().collation, "phonebk"); + assertEq(c3.resolvedOptions().collation, "phonebk"); + + assertEq(c1.compare("ä", "ae"), -1); + assertEq(c2.compare("ä", "ae"), 1); + assertEq(c3.compare("ä", "ae"), 1); +} + +// Collation property overrides any Unicode locale extension. +{ + let c1 = new Intl.Collator("de-u-co-eor", {usage: "sort"}); + let c2 = new Intl.Collator("de-u-co-eor", {usage: "sort", collation: "phonebk"}); + + // Ensure "eor" collation is supported. + assertEq(c1.resolvedOptions().locale, "de-u-co-eor"); + assertEq(c1.resolvedOptions().collation, "eor"); + + // "phonebk" property overrides the Unicode locale extension. + assertEq(c2.resolvedOptions().locale, "de"); + assertEq(c2.resolvedOptions().collation, "phonebk"); + + assertEq(c1.compare("ä", "ae"), -1); + assertEq(c2.compare("ä", "ae"), 1); +} + +// The default sort collation can't be requested. +{ + // The default sort collation for Swedish (sv) was "reformed" before CLDR 42. + // It wasn't possible to override this and select the default root sort + // collation. Use English (en) as a locale which uses the root sort collation + // for comparison. + let c1 = new Intl.Collator("sv", {usage: "sort"}); + let c2 = new Intl.Collator("sv-u-co-reformed", {usage: "sort"}); + let c3 = new Intl.Collator("sv-u-co-standard", {usage: "sort"}); + let c4 = new Intl.Collator("sv-u-co-default", {usage: "sort"}); + let c5 = new Intl.Collator("en", {usage: "sort"}); + + assertEq(c1.resolvedOptions().locale, "sv"); + assertEq(c2.resolvedOptions().locale, "sv"); + assertEq(c3.resolvedOptions().locale, "sv"); + assertEq(c4.resolvedOptions().locale, "sv"); + assertEq(c5.resolvedOptions().locale, "en"); + + assertEq(c1.resolvedOptions().collation, "default"); + assertEq(c2.resolvedOptions().collation, "default"); + assertEq(c3.resolvedOptions().collation, "default"); + assertEq(c4.resolvedOptions().collation, "default"); + assertEq(c5.resolvedOptions().collation, "default"); + + assertEq(c1.compare("y", "ü"), -1); + assertEq(c2.compare("y", "ü"), -1); + assertEq(c3.compare("y", "ü"), -1); + assertEq(c4.compare("y", "ü"), -1); + assertEq(c5.compare("y", "ü"), 1); +} + +// Search collations ignore any collation overrides. +{ + let c1 = new Intl.Collator("de", {usage: "search"}); + let c2 = new Intl.Collator("de", {usage: "search", collation: "phonebk"}); + let c3 = new Intl.Collator("de-u-co-phonebk", {usage: "search"}); + + assertEq(c1.resolvedOptions().locale, "de"); + assertEq(c2.resolvedOptions().locale, "de"); + assertEq(c3.resolvedOptions().locale, "de"); + + assertEq(c1.resolvedOptions().collation, "default"); + assertEq(c2.resolvedOptions().collation, "default"); + assertEq(c3.resolvedOptions().collation, "default"); + + assertEq(c1.compare("ä", "ae"), 1); + assertEq(c2.compare("ä", "ae"), 1); + assertEq(c3.compare("ä", "ae"), 1); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/Collator/compare.js b/js/src/tests/non262/Intl/Collator/compare.js new file mode 100644 index 0000000000..6f57c722dd --- /dev/null +++ b/js/src/tests/non262/Intl/Collator/compare.js @@ -0,0 +1,137 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Tests the compare function with a diverse set of locales and options. + +var input = [ + "Argentina", + "Oerlikon", + "Offenbach", + "Sverige", + "Vaticano", + "Zimbabwe", + "la France", + "¡viva España!", + "Österreich", + "中国", + "日本", + "한국", +]; + +var collator, expected; + +function assertEqualArray(actual, expected, collator) { + var description = JSON.stringify(collator.resolvedOptions()); + assertEq(actual.length, expected.length, "array length, " + description); + for (var i = 0; i < actual.length; i++) { + assertEq(actual[i], expected[i], "element " + i + ", " + description); + } +} + + +// Locale en-US; default options. +collator = new Intl.Collator("en-US"); +expected = [ + "¡viva España!", + "Argentina", + "la France", + "Oerlikon", + "Offenbach", + "Österreich", + "Sverige", + "Vaticano", + "Zimbabwe", + "한국", + "中国", + "日本", +]; +assertEqualArray(input.sort(collator.compare), expected, collator); + +// Locale sv-SE; default options. +// Swedish treats "Ö" as a separate character, which sorts after "Z". +collator = new Intl.Collator("sv-SE"); +expected = [ + "¡viva España!", + "Argentina", + "la France", + "Oerlikon", + "Offenbach", + "Sverige", + "Vaticano", + "Zimbabwe", + "Österreich", + "한국", + "中国", + "日本", +]; +assertEqualArray(input.sort(collator.compare), expected, collator); + +// Locale sv-SE; ignore punctuation. +collator = new Intl.Collator("sv-SE", {ignorePunctuation: true}); +expected = [ + "Argentina", + "la France", + "Oerlikon", + "Offenbach", + "Sverige", + "Vaticano", + "¡viva España!", + "Zimbabwe", + "Österreich", + "한국", + "中国", + "日本", +]; +assertEqualArray(input.sort(collator.compare), expected, collator); + +// Locale de-DE; default options. +// In German standard sorting, umlauted characters are treated as variants +// of their base characters: ä ≅ a, ö ≅ o, ü ≅ u. +collator = new Intl.Collator("de-DE"); +expected = [ + "¡viva España!", + "Argentina", + "la France", + "Oerlikon", + "Offenbach", + "Österreich", + "Sverige", + "Vaticano", + "Zimbabwe", + "한국", + "中国", + "日本", +]; +assertEqualArray(input.sort(collator.compare), expected, collator); + +// Locale de-DE; phonebook sort order. +// In German phonebook sorting, umlauted characters are expanded to two-vowel +// sequences: ä → ae, ö → oe, ü → ue. +collator = new Intl.Collator("de-DE-u-co-phonebk"); +expected = [ + "¡viva España!", + "Argentina", + "la France", + "Oerlikon", + "Österreich", + "Offenbach", + "Sverige", + "Vaticano", + "Zimbabwe", + "한국", + "中国", + "日本", +]; +assertEqualArray(input.sort(collator.compare), expected, collator); + + +// Test the .name property of the "compare" getter. +var desc = Object.getOwnPropertyDescriptor(Intl.Collator.prototype, "compare"); +assertEq(desc !== undefined, true); +assertEq(typeof desc.get, "function"); +assertEq(desc.get.name, "get compare"); + + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Intl/Collator/construct-newtarget.js b/js/src/tests/non262/Intl/Collator/construct-newtarget.js new file mode 100644 index 0000000000..5db1abf373 --- /dev/null +++ b/js/src/tests/non262/Intl/Collator/construct-newtarget.js @@ -0,0 +1,81 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +// Test subclassing %Intl.Collator% works correctly. +class MyCollator extends Intl.Collator {} + +var obj = new MyCollator(); +assertEq(obj instanceof MyCollator, true); +assertEq(obj instanceof Intl.Collator, true); +assertEq(Object.getPrototypeOf(obj), MyCollator.prototype); + +obj = Reflect.construct(MyCollator, []); +assertEq(obj instanceof MyCollator, true); +assertEq(obj instanceof Intl.Collator, true); +assertEq(Object.getPrototypeOf(obj), MyCollator.prototype); + +obj = Reflect.construct(MyCollator, [], MyCollator); +assertEq(obj instanceof MyCollator, true); +assertEq(obj instanceof Intl.Collator, true); +assertEq(Object.getPrototypeOf(obj), MyCollator.prototype); + +obj = Reflect.construct(MyCollator, [], Intl.Collator); +assertEq(obj instanceof MyCollator, false); +assertEq(obj instanceof Intl.Collator, true); +assertEq(Object.getPrototypeOf(obj), Intl.Collator.prototype); + + +// Set a different constructor as NewTarget. +obj = Reflect.construct(MyCollator, [], Array); +assertEq(obj instanceof MyCollator, false); +assertEq(obj instanceof Intl.Collator, false); +assertEq(obj instanceof Array, true); +assertEq(Object.getPrototypeOf(obj), Array.prototype); + +obj = Reflect.construct(Intl.Collator, [], Array); +assertEq(obj instanceof Intl.Collator, false); +assertEq(obj instanceof Array, true); +assertEq(Object.getPrototypeOf(obj), Array.prototype); + + +// The prototype defaults to %CollatorPrototype% if null. +function NewTargetNullPrototype() {} +NewTargetNullPrototype.prototype = null; + +obj = Reflect.construct(Intl.Collator, [], NewTargetNullPrototype); +assertEq(obj instanceof Intl.Collator, true); +assertEq(Object.getPrototypeOf(obj), Intl.Collator.prototype); + +obj = Reflect.construct(MyCollator, [], NewTargetNullPrototype); +assertEq(obj instanceof MyCollator, false); +assertEq(obj instanceof Intl.Collator, true); +assertEq(Object.getPrototypeOf(obj), Intl.Collator.prototype); + + +// "prototype" property is retrieved exactly once. +var trapLog = [], getLog = []; +var ProxiedConstructor = new Proxy(Intl.Collator, new Proxy({ + get(target, propertyKey, receiver) { + getLog.push(propertyKey); + return Reflect.get(target, propertyKey, receiver); + } +}, { + get(target, propertyKey, receiver) { + trapLog.push(propertyKey); + return Reflect.get(target, propertyKey, receiver); + } +})); + +obj = Reflect.construct(Intl.Collator, [], ProxiedConstructor); +assertEqArray(trapLog, ["get"]); +assertEqArray(getLog, ["prototype"]); +assertEq(obj instanceof Intl.Collator, true); +assertEq(Object.getPrototypeOf(obj), Intl.Collator.prototype); + + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/Collator/cross-compartment.js b/js/src/tests/non262/Intl/Collator/cross-compartment.js new file mode 100644 index 0000000000..a8cf3134ca --- /dev/null +++ b/js/src/tests/non262/Intl/Collator/cross-compartment.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +var otherGlobal = newGlobal(); + +var collator = new Intl.Collator(); +var ccwCollator = new otherGlobal.Intl.Collator(); + +// Test Intl.Collator.prototype.compare with a CCW object. +var Intl_Collator_compare_get = Object.getOwnPropertyDescriptor(Intl.Collator.prototype, "compare").get; + +assertEq(Intl_Collator_compare_get.call(ccwCollator)("a", "A"), + Intl_Collator_compare_get.call(collator)("a", "A")); + +// Test Intl.Collator.prototype.resolvedOptions with a CCW object. +var Intl_Collator_resolvedOptions = Intl.Collator.prototype.resolvedOptions; + +assertEq(deepEqual(Intl_Collator_resolvedOptions.call(ccwCollator), + Intl_Collator_resolvedOptions.call(collator)), + true); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/Collator/ignorePunctuation.js b/js/src/tests/non262/Intl/Collator/ignorePunctuation.js new file mode 100644 index 0000000000..281563cc5c --- /dev/null +++ b/js/src/tests/non262/Intl/Collator/ignorePunctuation.js @@ -0,0 +1,60 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +function testPunctuation(col, expectedIgnorePunctuation) { + let ignorePunctuation = col.resolvedOptions().ignorePunctuation; + assertEq(ignorePunctuation, expectedIgnorePunctuation); + + // Punctuation is ignored iff |ignorePunctuation| is true. + assertEq(col.compare("", "*"), ignorePunctuation ? 0 : -1); + + // Whitespace is also ignored when |ignorePunctuation| is true due to ICU limitations. + assertEq(col.compare("", " "), ignorePunctuation ? 0 : -1); +} + +const locales = [ + "en", "de", "fr", "it", "es", "ar", "zh", "ja", + + // Thai, including some subtags. + "th", "th-Thai", "th-TH", "th-u-kf-false", +]; + +for (let locale of locales) { + // Thai ignores punctuation by default. + let isThai = new Intl.Locale(locale).language === "th"; + + // Using default "ignorePunctuation" option. + testPunctuation(new Intl.Collator(locale, {}), isThai); + + // Using explicit "ignorePunctuation" option. + for (let ignorePunctuation of [true, false]) { + testPunctuation(new Intl.Collator(locale, {ignorePunctuation}), ignorePunctuation); + } +} + +if (typeof getDefaultLocale === "undefined") { + var getDefaultLocale = SpecialPowers.Cu.getJSTestingFunctions().getDefaultLocale; +} +if (typeof setDefaultLocale === "undefined") { + var setDefaultLocale = SpecialPowers.Cu.getJSTestingFunctions().setDefaultLocale; +} + +const defaultLocale = getDefaultLocale(); + +function withLocale(locale, fn) { + setDefaultLocale(locale); + try { + fn(); + } finally { + setDefaultLocale(defaultLocale); + } +} + +// Ensure this works correctly when Thai is the default locale. +for (let locale of ["th", "th-TH"]) { + withLocale(locale, () => { + testPunctuation(new Intl.Collator(undefined, {}), true); + }); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/Collator/implicithan.js b/js/src/tests/non262/Intl/Collator/implicithan.js new file mode 100644 index 0000000000..518ecdb43e --- /dev/null +++ b/js/src/tests/non262/Intl/Collator/implicithan.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +let scrambled = ['𠙶', '𠇲', '㓙', '㑧', '假', '凷']; + +// Sort first by block and then by radical-stroke inside each block. +// This matches the ICU/ICU4X implicithan root order, which is used +// by Chrome as of October 2022. (As of October 2022, Safari uses +// the unihan root order, which uses more data but uses radical-stroke +// across blocks.) +const byBlock = ['假', '凷', '㑧', '㓙', '𠇲', '𠙶']; + +scrambled.sort(new Intl.Collator().compare); +assertEqArray(scrambled, byBlock); + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Intl/Collator/shell.js b/js/src/tests/non262/Intl/Collator/shell.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Intl/Collator/supportedLocalesOf.js b/js/src/tests/non262/Intl/Collator/supportedLocalesOf.js new file mode 100644 index 0000000000..7fbebca094 --- /dev/null +++ b/js/src/tests/non262/Intl/Collator/supportedLocalesOf.js @@ -0,0 +1,355 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")||xulRuntime.shell) +// -- test in browser only that ICU has locale data for all Mozilla languages + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// This array contains the locales that ICU supports in +// collation whose languages Mozilla localizes Firefox into. +// Current as of ICU 50.1.2 and Firefox March 2013. +var locales = [ + "af", + "af-NA", + "af-ZA", + "ar", + "ar-001", + "ar-AE", + "ar-BH", + "ar-DJ", + "ar-DZ", + "ar-EG", + "ar-EH", + "ar-ER", + "ar-IL", + "ar-IQ", + "ar-JO", + "ar-KM", + "ar-KW", + "ar-LB", + "ar-LY", + "ar-MA", + "ar-MR", + "ar-OM", + "ar-PS", + "ar-QA", + "ar-SA", + "ar-SD", + "ar-SO", + "ar-SY", + "ar-TD", + "ar-TN", + "ar-YE", + "as", + "as-IN", + "be", + "be-BY", + "bg", + "bg-BG", + "bn", + "bn-BD", + "bn-IN", + "bs", + "bs-Cyrl", + "bs-Cyrl-BA", + "bs-Latn", + "bs-Latn-BA", + "ca", + "ca-AD", + "ca-ES", + "cs", + "cs-CZ", + "cy", + "cy-GB", + "da", + "da-DK", + "de", + "de-AT", + "de-BE", + "de-CH", + "de-DE", + "de-LI", + "de-LU", + "el", + "el-CY", + "el-GR", + "en", + "en-150", + "en-AG", + "en-AS", + "en-AU", + "en-BB", + "en-BE", + "en-BM", + "en-BS", + "en-BW", + "en-BZ", + "en-CA", + "en-CM", + "en-DM", + "en-FJ", + "en-FM", + "en-GB", + "en-GD", + "en-GG", + "en-GH", + "en-GI", + "en-GM", + "en-GU", + "en-HK", + "en-IE", + "en-IM", + "en-IN", + "en-JE", + "en-JM", + "en-KE", + "en-KI", + "en-KN", + "en-KY", + "en-LC", + "en-LR", + "en-LS", + "en-MG", + "en-MH", + "en-MP", + "en-MT", + "en-MU", + "en-MW", + "en-NA", + "en-NG", + "en-NZ", + "en-PG", + "en-PH", + "en-PK", + "en-PR", + "en-PW", + "en-SB", + "en-SC", + "en-SG", + "en-SL", + "en-SS", + "en-TC", + "en-TO", + "en-TT", + "en-TZ", + "en-UG", + "en-UM", + "en-US", + "en-US-POSIX", + "en-VC", + "en-VG", + "en-VI", + "en-VU", + "en-WS", + "en-ZA", + "en-ZM", + "en-ZW", + "eo", + "es", + "es-419", + "es-AR", + "es-BO", + "es-CL", + "es-CO", + "es-CR", + "es-CU", + "es-DO", + "es-EA", + "es-EC", + "es-ES", + "es-GQ", + "es-GT", + "es-HN", + "es-IC", + "es-MX", + "es-NI", + "es-PA", + "es-PE", + "es-PH", + "es-PR", + "es-PY", + "es-SV", + "es-US", + "es-UY", + "es-VE", + "et", + "et-EE", + "fa", + "fa-AF", + "fa-IR", + "fi", + "fi-FI", + "fr", + "fr-BE", + "fr-BF", + "fr-BI", + "fr-BJ", + "fr-BL", + "fr-CA", + "fr-CD", + "fr-CF", + "fr-CG", + "fr-CH", + "fr-CI", + "fr-CM", + "fr-DJ", + "fr-DZ", + "fr-FR", + "fr-GA", + "fr-GN", + "fr-GP", + "fr-GQ", + "fr-HT", + "fr-KM", + "fr-LU", + "fr-MA", + "fr-MC", + "fr-MF", + "fr-MG", + "fr-ML", + "fr-MQ", + "fr-MR", + "fr-MU", + "fr-NC", + "fr-NE", + "fr-PF", + "fr-RE", + "fr-RW", + "fr-SC", + "fr-SN", + "fr-SY", + "fr-TD", + "fr-TG", + "fr-TN", + "fr-VU", + "ga", + "ga-IE", + "gu", + "gu-IN", + "he", + "he-IL", + "hi", + "hi-IN", + "hr", + "hr-BA", + "hr-HR", + "hu", + "hu-HU", + "hy", + "hy-AM", + "id", + "id-ID", + "is", + "is-IS", + "it", + "it-CH", + "it-IT", + "it-SM", + "ja", + "ja-JP", + "kk", + "kk-KZ", + "km", + "km-KH", + "kn", + "kn-IN", + "ko", + "ko-KP", + "ko-KR", + "lt", + "lt-LT", + "lv", + "lv-LV", + "mk", + "mk-MK", + "ml", + "ml-IN", + "mr", + "mr-IN", + "nb", + "nb-NO", + "nl", + "nl-AW", + "nl-BE", + "nl-CW", + "nl-NL", + "nl-SR", + "nl-SX", + "nn", + "nn-NO", + "or", + "or-IN", + "pa", + "pa-Arab", + "pa-Arab-PK", + "pa-Guru", + "pa-Guru-IN", + "pl", + "pl-PL", + "pt", + "pt-AO", + "pt-BR", + "pt-CV", + "pt-GW", + "pt-MO", + "pt-MZ", + "pt-PT", + "pt-ST", + "pt-TL", + "ro", + "ro-MD", + "ro-RO", + "ru", + "ru-BY", + "ru-KG", + "ru-KZ", + "ru-MD", + "ru-RU", + "ru-UA", + "si", + "si-LK", + "sk", + "sk-SK", + "sl", + "sl-SI", + "sq", + "sq-AL", + "sq-MK", + "sr", + "sr-Cyrl", + "sr-Cyrl-BA", + "sr-Cyrl-ME", + "sr-Cyrl-RS", + "sr-Latn", + "sr-Latn-BA", + "sr-Latn-ME", + "sr-Latn-RS", + "sv", + "sv-AX", + "sv-FI", + "sv-SE", + "te", + "te-IN", + "th", + "th-TH", + "tr", + "tr-CY", + "tr-TR", + "uk", + "uk-UA", + "vi", + "vi-VN", + "zh", + "zh-Hans", + "zh-Hans-CN", + "zh-Hans-SG", + "zh-Hant", + "zh-Hant-HK", + "zh-Hant-MO", + "zh-Hant-TW", +]; + + +var count = Intl.Collator.supportedLocalesOf(locales).length; + +reportCompare(locales.length, count, "Number of supported locales in Intl.Collator"); diff --git a/js/src/tests/non262/Intl/Collator/toStringTag.js b/js/src/tests/non262/Intl/Collator/toStringTag.js new file mode 100644 index 0000000000..e092418df9 --- /dev/null +++ b/js/src/tests/non262/Intl/Collator/toStringTag.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var desc = Object.getOwnPropertyDescriptor(Intl.Collator.prototype, Symbol.toStringTag); + +assertEq(desc !== undefined, true); +assertEq(desc.value, "Intl.Collator"); +assertEq(desc.writable, false); +assertEq(desc.enumerable, false); +assertEq(desc.configurable, true); + +assertEq(Object.prototype.toString.call(Intl.Collator.prototype), "[object Intl.Collator]"); +assertEq(Object.prototype.toString.call(new Intl.Collator), "[object Intl.Collator]"); + +Object.defineProperty(Intl.Collator.prototype, Symbol.toStringTag, {value: "Collator"}); + +assertEq(Object.prototype.toString.call(Intl.Collator.prototype), "[object Collator]"); +assertEq(Object.prototype.toString.call(new Intl.Collator), "[object Collator]"); + +delete Intl.Collator.prototype[Symbol.toStringTag]; + +assertEq(Object.prototype.toString.call(Intl.Collator.prototype), "[object Object]"); +assertEq(Object.prototype.toString.call(new Intl.Collator), "[object Object]"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/Date/browser.js b/js/src/tests/non262/Intl/Date/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Intl/Date/shell.js b/js/src/tests/non262/Intl/Date/shell.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Intl/Date/toLocaleDateString_timeZone.js b/js/src/tests/non262/Intl/Date/toLocaleDateString_timeZone.js new file mode 100644 index 0000000000..e3c3013d30 --- /dev/null +++ b/js/src/tests/non262/Intl/Date/toLocaleDateString_timeZone.js @@ -0,0 +1,77 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const defaultLocale = "en-US"; +const defaultDate = Date.UTC(2012, 12-1, 6, 12, 0, 0); +const defaultOptions = { timeZoneName: "short" }; + +const tests = [ + { + timeZone: "UTC", + result: "12/6/2012, UTC", + }, + { + timeZone: "America/Los_Angeles", + result: "12/6/2012, PST", + }, + { + timeZone: "Europe/Berlin", locale: "de", + options: { timeZoneName: "short" }, + result: "6.12.2012, MEZ", + }, + { + timeZone: "Europe/Paris", locale: "fr", + options: { timeZoneName: "long" }, + result: "06/12/2012 heure normale d’Europe centrale", + }, + { + timeZone: "Asia/Shanghai", locale: "zh-Hans-CN", + options: { timeZoneName: "long" }, + result: "2012/12/6 中国标准时间", + }, + { + timeZone: { toString: () => "Australia/Melbourne" }, locale: "en-AU", + result: "06/12/2012, AEDT", + }, +]; + +for (let {timeZone, result, locale = defaultLocale, date = defaultDate, options = defaultOptions} of tests) { + let s = new Date(date).toLocaleDateString(locale, Object.assign({timeZone}, options)); + assertEq(s, result); +} + + +// |undefined| or absent "timeZone" option selects the default time zone. +{ + let locale = defaultLocale; + let date = defaultDate; + let options = defaultOptions; + + let absentTz = new Date(date).toLocaleDateString(locale, Object.assign({}, options)); + let undefinedTz = new Date(date).toLocaleDateString(locale, Object.assign({timeZone: undefined}, options)); + assertEq(undefinedTz, absentTz); +} + + +// RangeError is thrown for invalid time zone names. +for (let timeZone of ["", "undefined", "UTC\0", "Vienna", "Africa", "America/NewYork"]) { + assertThrowsInstanceOf(() => { + new Date(defaultDate).toLocaleDateString(undefined, {timeZone}); + }, RangeError); +} + +// RangeError is thrown for these values, because ToString() +// isn't a valid time zone name. +for (let timeZone of [null, 0, 0.5, true, false, [], {}, function() {}]) { + assertThrowsInstanceOf(() => { + new Date(defaultDate).toLocaleDateString(undefined, {timeZone}); + }, RangeError); +} + +// ToString() throws TypeError. +assertThrowsInstanceOf(() => { + new Date(defaultDate).toLocaleDateString(undefined, {timeZone: Symbol()}); +}, TypeError); + + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/Date/toLocaleString_timeZone.js b/js/src/tests/non262/Intl/Date/toLocaleString_timeZone.js new file mode 100644 index 0000000000..592e55070c --- /dev/null +++ b/js/src/tests/non262/Intl/Date/toLocaleString_timeZone.js @@ -0,0 +1,77 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const defaultLocale = "en-US"; +const defaultDate = Date.UTC(2012, 12-1, 6, 12, 0, 0); +const defaultOptions = {}; + +const tests = [ + { + timeZone: "UTC", + result: "12/6/2012, 12:00:00 PM", + }, + { + timeZone: "America/Los_Angeles", + result: "12/6/2012, 4:00:00 AM", + }, + { + timeZone: "Europe/Berlin", locale: "de", + options: { timeZoneName: "short" }, + result: "6.12.2012, 13:00:00 MEZ", + }, + { + timeZone: "Europe/Paris", locale: "fr", + options: { timeZoneName: "long" }, + result: "06/12/2012 13:00:00 heure normale d’Europe centrale", + }, + { + timeZone: "Asia/Shanghai", locale: "zh-Hans-CN", + options: { timeZoneName: "long" }, + result: "2012/12/6 中国标准时间 20:00:00", + }, + { + timeZone: { toString: () => "Australia/Melbourne" }, locale: "en-AU", + result: "06/12/2012, 11:00:00 pm", + }, +]; + +for (let {timeZone, result, locale = defaultLocale, date = defaultDate, options = defaultOptions} of tests) { + let s = new Date(date).toLocaleString(locale, Object.assign({timeZone}, options)); + assertEq(s, result); +} + + +// |undefined| or absent "timeZone" option selects the default time zone. +{ + let locale = defaultLocale; + let date = defaultDate; + let options = defaultOptions; + + let absentTz = new Date(date).toLocaleString(locale, Object.assign({}, options)); + let undefinedTz = new Date(date).toLocaleString(locale, Object.assign({timeZone: undefined}, options)); + assertEq(undefinedTz, absentTz); +} + + +// RangeError is thrown for invalid time zone names. +for (let timeZone of ["", "undefined", "UTC\0", "Vienna", "Africa", "America/NewYork"]) { + assertThrowsInstanceOf(() => { + new Date(defaultDate).toLocaleString(undefined, {timeZone}); + }, RangeError); +} + +// RangeError is thrown for these values, because ToString() +// isn't a valid time zone name. +for (let timeZone of [null, 0, 0.5, true, false, [], {}, function() {}]) { + assertThrowsInstanceOf(() => { + new Date(defaultDate).toLocaleString(undefined, {timeZone}); + }, RangeError); +} + +// ToString() throws TypeError. +assertThrowsInstanceOf(() => { + new Date(defaultDate).toLocaleString(undefined, {timeZone: Symbol()}); +}, TypeError); + + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/Date/toLocaleTimeString_timeZone.js b/js/src/tests/non262/Intl/Date/toLocaleTimeString_timeZone.js new file mode 100644 index 0000000000..a9b8b5f980 --- /dev/null +++ b/js/src/tests/non262/Intl/Date/toLocaleTimeString_timeZone.js @@ -0,0 +1,77 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const defaultLocale = "en-US"; +const defaultDate = Date.UTC(2012, 12-1, 6, 12, 0, 0); +const defaultOptions = {}; + +const tests = [ + { + timeZone: "UTC", + result: "12:00:00 PM", + }, + { + timeZone: "America/Los_Angeles", + result: "4:00:00 AM", + }, + { + timeZone: "Europe/Berlin", locale: "de", + options: { timeZoneName: "short" }, + result: "13:00:00 MEZ", + }, + { + timeZone: "Europe/Paris", locale: "fr", + options: { timeZoneName: "long" }, + result: "13:00:00 heure normale d’Europe centrale", + }, + { + timeZone: "Asia/Shanghai", locale: "zh-Hans-CN", + options: { timeZoneName: "long" }, + result: "中国标准时间 20:00:00", + }, + { + timeZone: { toString: () => "Australia/Melbourne" }, locale: "en-AU", + result: "11:00:00 pm", + }, +]; + +for (let {timeZone, result, locale = defaultLocale, date = defaultDate, options = defaultOptions} of tests) { + let s = new Date(date).toLocaleTimeString(locale, Object.assign({timeZone}, options)); + assertEq(s, result); +} + + +// |undefined| or absent "timeZone" option selects the default time zone. +{ + let locale = defaultLocale; + let date = defaultDate; + let options = defaultOptions; + + let absentTz = new Date(date).toLocaleTimeString(locale, Object.assign({}, options)); + let undefinedTz = new Date(date).toLocaleTimeString(locale, Object.assign({timeZone: undefined}, options)); + assertEq(undefinedTz, absentTz); +} + + +// RangeError is thrown for invalid time zone names. +for (let timeZone of ["", "undefined", "UTC\0", "Vienna", "Africa", "America/NewYork"]) { + assertThrowsInstanceOf(() => { + new Date(defaultDate).toLocaleTimeString(undefined, {timeZone}); + }, RangeError); +} + +// RangeError is thrown for these values, because ToString() +// isn't a valid time zone name. +for (let timeZone of [null, 0, 0.5, true, false, [], {}, function() {}]) { + assertThrowsInstanceOf(() => { + new Date(defaultDate).toLocaleTimeString(undefined, {timeZone}); + }, RangeError); +} + +// ToString() throws TypeError. +assertThrowsInstanceOf(() => { + new Date(defaultDate).toLocaleTimeString(undefined, {timeZone: Symbol()}); +}, TypeError); + + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/browser.js b/js/src/tests/non262/Intl/DateTimeFormat/browser.js new file mode 100644 index 0000000000..5665e7ed44 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/browser.js @@ -0,0 +1,3 @@ +if (typeof setTimeZone === "undefined") { + var setTimeZone = SpecialPowers.Cu.getJSTestingFunctions().setTimeZone; +} diff --git a/js/src/tests/non262/Intl/DateTimeFormat/calendar-aliases.js b/js/src/tests/non262/Intl/DateTimeFormat/calendar-aliases.js new file mode 100644 index 0000000000..901adcb45f --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/calendar-aliases.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Ensure ethiopic-amete-alem is resolved to ethioaa instead of ethiopic. +function testEthiopicAmeteAlem() { + var locale = "am-ET-u-nu-latn"; + var opts = {timeZone: "Africa/Addis_Ababa"}; + var dtfEthiopicAmeteAlem = new Intl.DateTimeFormat(`${locale}-ca-ethiopic-amete-alem`, opts); + var dtfEthioaa = new Intl.DateTimeFormat(`${locale}-ca-ethioaa`, opts); + var dtfEthiopic = new Intl.DateTimeFormat(`${locale}-ca-ethiopic`, opts); + + var date = new Date(2016, 1 - 1, 1); + + assertEq(dtfEthiopicAmeteAlem.format(date), dtfEthioaa.format(date)); + assertEq(dtfEthiopicAmeteAlem.format(date) === dtfEthiopic.format(date), false); +} + +// Ensure islamicc is resolved to islamic-civil. +function testIslamicCivil() { + var locale = "ar-SA-u-nu-latn"; + var opts = {timeZone: "Asia/Riyadh"}; + var dtfIslamicCivil = new Intl.DateTimeFormat(`${locale}-ca-islamic-civil`, opts); + var dtfIslamicc = new Intl.DateTimeFormat(`${locale}-ca-islamicc`, opts); + var dtfIslamic = new Intl.DateTimeFormat(`${locale}-ca-islamic`, opts); + + var date = new Date(2016, 1 - 1, 1); + + assertEq(dtfIslamicCivil.format(date), dtfIslamicc.format(date)); + assertEq(dtfIslamicCivil.format(date) === dtfIslamic.format(date), false); +} + +testEthiopicAmeteAlem(); +testIslamicCivil(); + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/calendar-option.js b/js/src/tests/non262/Intl/DateTimeFormat/calendar-option.js new file mode 100644 index 0000000000..cbf73df5c9 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/calendar-option.js @@ -0,0 +1,67 @@ +const defaultLocale = "en"; +const defaultCalendar = new Intl.DateTimeFormat(defaultLocale).resolvedOptions().calendar; + +function createWithLocale(locale, calendar) { + return new Intl.DateTimeFormat(locale, {calendar}); +} + +function create(calendar) { + return createWithLocale(defaultLocale, calendar); +} + +// Empty string should throw. +assertThrowsInstanceOf(() => create(""), RangeError); + +// Trailing \0 should throw. +assertThrowsInstanceOf(() => create("gregory\0"), RangeError); + +// Too short or too long strings should throw. +assertThrowsInstanceOf(() => create("a"), RangeError); +assertThrowsInstanceOf(() => create("toolongstring"), RangeError); + +// Throw even when prefix is valid. +assertThrowsInstanceOf(() => create("gregory-toolongstring"), RangeError); + +// |calendar| can be set to |undefined|. +let dtf = create(undefined); +assertEq(dtf.resolvedOptions().calendar, defaultCalendar); + +// Unsupported calendars are ignored. +dtf = create("xxxxxxxx"); +assertEq(dtf.resolvedOptions().calendar, defaultCalendar); + +// Calendars in options overwrite Unicode extension keyword. +dtf = createWithLocale(`${defaultLocale}-u-ca-iso8601`, "japanese"); +assertEq(dtf.resolvedOptions().locale, defaultLocale); +assertEq(dtf.resolvedOptions().calendar, "japanese"); + +// |calendar| option ignores case. +dtf = create("CHINESE"); +assertEq(dtf.resolvedOptions().locale, defaultLocale); +assertEq(dtf.resolvedOptions().calendar, "chinese"); + +const calendars = [ + "buddhist", "chinese", "coptic", "dangi", "ethioaa", "ethiopic-amete-alem", + "ethiopic", "gregory", "hebrew", "indian", "islamic", "islamic-umalqura", + "islamic-tbla", "islamic-civil", "islamic-rgsa", "iso8601", "japanese", + "persian", "roc", "islamicc", +]; + +// https://github.com/tc39/proposal-intl-locale/issues/96 +const canonical = { + "islamicc": "islamic-civil", + "ethiopic-amete-alem": "ethioaa", +}; + +for (let calendar of calendars) { + let dtf1 = new Intl.DateTimeFormat(`${defaultLocale}-u-ca-${calendar}`); + let dtf2 = new Intl.DateTimeFormat(defaultLocale, {calendar}); + + assertEq(dtf1.resolvedOptions().calendar, canonical[calendar] ?? calendar); + assertEq(dtf2.resolvedOptions().calendar, canonical[calendar] ?? calendar); + + assertEq(dtf2.format(0), dtf1.format(0)); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/call.js b/js/src/tests/non262/Intl/DateTimeFormat/call.js new file mode 100644 index 0000000000..752bda9c02 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/call.js @@ -0,0 +1,184 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +function IsIntlService(c) { + return typeof c === "function" && + c.hasOwnProperty("prototype") && + c.prototype.hasOwnProperty("resolvedOptions"); +} + +function IsObject(o) { + return Object(o) === o; +} + +function IsPrimitive(o) { + return Object(o) !== o; +} + +function thisValues() { + const intlConstructors = Object.getOwnPropertyNames(Intl).map(name => Intl[name]).filter(IsIntlService); + + return [ + // Primitive values. + ...[undefined, null, true, "abc", Symbol(), 123], + + // Object values. + ...[{}, [], /(?:)/, function(){}, new Proxy({}, {})], + + // Intl objects. + ...[].concat(...intlConstructors.map(ctor => { + let args = []; + if (ctor === Intl.DisplayNames) { + // Intl.DisplayNames can't be constructed without any arguments. + args = [undefined, {type: "language"}]; + } + + return [ + // Instance of an Intl constructor. + new ctor(...args), + + // Instance of a subclassed Intl constructor. + new class extends ctor {}(...args), + + // Object inheriting from an Intl constructor prototype. + Object.create(ctor.prototype), + + // Intl object not inheriting from its default prototype. + Object.setPrototypeOf(new ctor(...args), Object.prototype), + ]; + })), + ]; +} + +const intlFallbackSymbol = Object.getOwnPropertySymbols(Intl.DateTimeFormat.call(Object.create(Intl.DateTimeFormat.prototype)))[0]; + +// Invoking [[Call]] for Intl.DateTimeFormat returns a new instance unless called +// with an instance inheriting from Intl.DateTimeFormat.prototype. +for (let thisValue of thisValues()) { + let obj = Intl.DateTimeFormat.call(thisValue); + + if (!Intl.DateTimeFormat.prototype.isPrototypeOf(thisValue)) { + assertEq(Object.is(obj, thisValue), false); + assertEq(obj instanceof Intl.DateTimeFormat, true); + if (IsObject(thisValue)) + assertEqArray(Object.getOwnPropertySymbols(thisValue), []); + } else { + assertEq(Object.is(obj, thisValue), true); + assertEq(obj instanceof Intl.DateTimeFormat, true); + assertEqArray(Object.getOwnPropertySymbols(thisValue), [intlFallbackSymbol]); + } +} + +// Intl.DateTimeFormat uses the legacy Intl constructor compromise semantics. +// - Test when InstanceofOperator(thisValue, %DateTimeFormat%) returns true. +for (let thisValue of thisValues().filter(IsObject)) { + let isPrototypeOf = Intl.DateTimeFormat.prototype.isPrototypeOf(thisValue); + let hasInstanceCalled = false; + Object.defineProperty(Intl.DateTimeFormat, Symbol.hasInstance, { + value() { + assertEq(hasInstanceCalled, false); + hasInstanceCalled = true; + return true; + }, configurable: true + }); + let obj = Intl.DateTimeFormat.call(thisValue); + delete Intl.DateTimeFormat[Symbol.hasInstance]; + + assertEq(Object.is(obj, thisValue), isPrototypeOf); + assertEq(hasInstanceCalled, false); + assertEqArray(Object.getOwnPropertySymbols(thisValue), isPrototypeOf ? [intlFallbackSymbol] : []); +} +// - Test when InstanceofOperator(thisValue, %DateTimeFormat%) returns false. +for (let thisValue of thisValues().filter(IsObject)) { + let isPrototypeOf = Intl.DateTimeFormat.prototype.isPrototypeOf(thisValue); + let hasInstanceCalled = false; + Object.defineProperty(Intl.DateTimeFormat, Symbol.hasInstance, { + value() { + assertEq(hasInstanceCalled, false); + hasInstanceCalled = true; + return false; + }, configurable: true + }); + let obj = Intl.DateTimeFormat.call(thisValue); + delete Intl.DateTimeFormat[Symbol.hasInstance]; + + assertEq(Object.is(obj, thisValue), isPrototypeOf); + assertEq(obj instanceof Intl.DateTimeFormat, true); + assertEq(hasInstanceCalled, false); + assertEqArray(Object.getOwnPropertySymbols(thisValue), isPrototypeOf ? [intlFallbackSymbol] : []); +} +// - Test with primitive values. +for (let thisValue of thisValues().filter(IsPrimitive)) { + // Ensure @@hasInstance is not called. + Object.defineProperty(Intl.DateTimeFormat, Symbol.hasInstance, { + value() { assertEq(true, false); }, configurable: true + }); + let obj = Intl.DateTimeFormat.call(thisValue); + delete Intl.DateTimeFormat[Symbol.hasInstance]; + + assertEq(Object.is(obj, thisValue), false); + assertEq(obj instanceof Intl.DateTimeFormat, true); +} + +// Throws an error when attempting to install [[FallbackSymbol]] twice. +{ + let thisValue = Object.create(Intl.DateTimeFormat.prototype); + assertEqArray(Object.getOwnPropertySymbols(thisValue), []); + + assertEq(Intl.DateTimeFormat.call(thisValue), thisValue); + assertEqArray(Object.getOwnPropertySymbols(thisValue), [intlFallbackSymbol]); + + assertThrowsInstanceOf(() => Intl.DateTimeFormat.call(thisValue), TypeError); + assertEqArray(Object.getOwnPropertySymbols(thisValue), [intlFallbackSymbol]); +} + +// Throws an error when the thisValue is non-extensible. +{ + let thisValue = Object.create(Intl.DateTimeFormat.prototype); + Object.preventExtensions(thisValue); + + assertThrowsInstanceOf(() => Intl.DateTimeFormat.call(thisValue), TypeError); + assertEqArray(Object.getOwnPropertySymbols(thisValue), []); +} + +// [[FallbackSymbol]] is installed as a frozen property holding an Intl.DateTimeFormat instance. +{ + let thisValue = Object.create(Intl.DateTimeFormat.prototype); + Intl.DateTimeFormat.call(thisValue); + + let desc = Object.getOwnPropertyDescriptor(thisValue, intlFallbackSymbol); + assertEq(desc !== undefined, true); + assertEq(desc.writable, false); + assertEq(desc.enumerable, false); + assertEq(desc.configurable, false); + assertEq(desc.value instanceof Intl.DateTimeFormat, true); +} + +// Ensure [[FallbackSymbol]] is installed last by changing the [[Prototype]] +// during initialization. +{ + let thisValue = {}; + let options = { + get hour12() { + Object.setPrototypeOf(thisValue, Intl.DateTimeFormat.prototype); + return false; + } + }; + let obj = Intl.DateTimeFormat.call(thisValue, undefined, options); + assertEq(Object.is(obj, thisValue), true); + assertEqArray(Object.getOwnPropertySymbols(thisValue), [intlFallbackSymbol]); +} +{ + let thisValue = Object.create(Intl.DateTimeFormat.prototype); + let options = { + get hour12() { + Object.setPrototypeOf(thisValue, Object.prototype); + return false; + } + }; + let obj = Intl.DateTimeFormat.call(thisValue, undefined, options); + assertEq(Object.is(obj, thisValue), false); + assertEqArray(Object.getOwnPropertySymbols(thisValue), []); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/construct-newtarget.js b/js/src/tests/non262/Intl/DateTimeFormat/construct-newtarget.js new file mode 100644 index 0000000000..bbc08c79a1 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/construct-newtarget.js @@ -0,0 +1,81 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +// Test subclassing %Intl.DateTimeFormat% works correctly. +class MyDateTimeFormat extends Intl.DateTimeFormat {} + +var obj = new MyDateTimeFormat(); +assertEq(obj instanceof MyDateTimeFormat, true); +assertEq(obj instanceof Intl.DateTimeFormat, true); +assertEq(Object.getPrototypeOf(obj), MyDateTimeFormat.prototype); + +obj = Reflect.construct(MyDateTimeFormat, []); +assertEq(obj instanceof MyDateTimeFormat, true); +assertEq(obj instanceof Intl.DateTimeFormat, true); +assertEq(Object.getPrototypeOf(obj), MyDateTimeFormat.prototype); + +obj = Reflect.construct(MyDateTimeFormat, [], MyDateTimeFormat); +assertEq(obj instanceof MyDateTimeFormat, true); +assertEq(obj instanceof Intl.DateTimeFormat, true); +assertEq(Object.getPrototypeOf(obj), MyDateTimeFormat.prototype); + +obj = Reflect.construct(MyDateTimeFormat, [], Intl.DateTimeFormat); +assertEq(obj instanceof MyDateTimeFormat, false); +assertEq(obj instanceof Intl.DateTimeFormat, true); +assertEq(Object.getPrototypeOf(obj), Intl.DateTimeFormat.prototype); + + +// Set a different constructor as NewTarget. +obj = Reflect.construct(MyDateTimeFormat, [], Array); +assertEq(obj instanceof MyDateTimeFormat, false); +assertEq(obj instanceof Intl.DateTimeFormat, false); +assertEq(obj instanceof Array, true); +assertEq(Object.getPrototypeOf(obj), Array.prototype); + +obj = Reflect.construct(Intl.DateTimeFormat, [], Array); +assertEq(obj instanceof Intl.DateTimeFormat, false); +assertEq(obj instanceof Array, true); +assertEq(Object.getPrototypeOf(obj), Array.prototype); + + +// The prototype defaults to %DateTimeFormatPrototype% if null. +function NewTargetNullPrototype() {} +NewTargetNullPrototype.prototype = null; + +obj = Reflect.construct(Intl.DateTimeFormat, [], NewTargetNullPrototype); +assertEq(obj instanceof Intl.DateTimeFormat, true); +assertEq(Object.getPrototypeOf(obj), Intl.DateTimeFormat.prototype); + +obj = Reflect.construct(MyDateTimeFormat, [], NewTargetNullPrototype); +assertEq(obj instanceof MyDateTimeFormat, false); +assertEq(obj instanceof Intl.DateTimeFormat, true); +assertEq(Object.getPrototypeOf(obj), Intl.DateTimeFormat.prototype); + + +// "prototype" property is retrieved exactly once. +var trapLog = [], getLog = []; +var ProxiedConstructor = new Proxy(Intl.DateTimeFormat, new Proxy({ + get(target, propertyKey, receiver) { + getLog.push(propertyKey); + return Reflect.get(target, propertyKey, receiver); + } +}, { + get(target, propertyKey, receiver) { + trapLog.push(propertyKey); + return Reflect.get(target, propertyKey, receiver); + } +})); + +obj = Reflect.construct(Intl.DateTimeFormat, [], ProxiedConstructor); +assertEqArray(trapLog, ["get"]); +assertEqArray(getLog, ["prototype"]); +assertEq(obj instanceof Intl.DateTimeFormat, true); +assertEq(Object.getPrototypeOf(obj), Intl.DateTimeFormat.prototype); + + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/cross-compartment.js b/js/src/tests/non262/Intl/DateTimeFormat/cross-compartment.js new file mode 100644 index 0000000000..dac99bdc19 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/cross-compartment.js @@ -0,0 +1,70 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +var otherGlobal = newGlobal(); + +var dateTimeFormat = new Intl.DateTimeFormat(); +var ccwDateTimeFormat = new otherGlobal.Intl.DateTimeFormat(); + +// Test Intl.DateTimeFormat.prototype.format with a CCW object. +var Intl_DateTimeFormat_format_get = Object.getOwnPropertyDescriptor(Intl.DateTimeFormat.prototype, "format").get; + +assertEq(Intl_DateTimeFormat_format_get.call(ccwDateTimeFormat)(0), + Intl_DateTimeFormat_format_get.call(dateTimeFormat)(0)); + +// Test Intl.DateTimeFormat.prototype.formatToParts with a CCW object. +var Intl_DateTimeFormat_formatToParts = Intl.DateTimeFormat.prototype.formatToParts; + +assertEq(deepEqual(Intl_DateTimeFormat_formatToParts.call(ccwDateTimeFormat, 0), + Intl_DateTimeFormat_formatToParts.call(dateTimeFormat, 0)), + true); + +// Test Intl.DateTimeFormat.prototype.resolvedOptions with a CCW object. +var Intl_DateTimeFormat_resolvedOptions = Intl.DateTimeFormat.prototype.resolvedOptions; + +assertEq(deepEqual(Intl_DateTimeFormat_resolvedOptions.call(ccwDateTimeFormat), + Intl_DateTimeFormat_resolvedOptions.call(dateTimeFormat)), + true); + +// Special case for Intl.DateTimeFormat: The Intl fallback symbol. + +function fallbackSymbol(global) { + var DTF = global.Intl.DateTimeFormat; + return Object.getOwnPropertySymbols(DTF.call(Object.create(DTF.prototype)))[0]; +} + +const intlFallbackSymbol = fallbackSymbol(this); +const otherIntlFallbackSymbol = fallbackSymbol(otherGlobal); +assertEq(intlFallbackSymbol === otherIntlFallbackSymbol, false); + +// Test when the fallback symbol points to a CCW DateTimeFormat object. +var objWithFallbackCCWDateTimeFormat = { + __proto__: Intl.DateTimeFormat.prototype, + [intlFallbackSymbol]: ccwDateTimeFormat, +}; + +assertEq(Intl_DateTimeFormat_format_get.call(objWithFallbackCCWDateTimeFormat)(0), + Intl_DateTimeFormat_format_get.call(dateTimeFormat)(0)); + +assertEq(deepEqual(Intl_DateTimeFormat_resolvedOptions.call(objWithFallbackCCWDateTimeFormat), + Intl_DateTimeFormat_resolvedOptions.call(dateTimeFormat)), + true); + +// Ensure the fallback symbol(s) are not accessed for CCW DateTimeFormat objects. +var ccwDateTimeFormatWithPoisonedFallback = new otherGlobal.Intl.DateTimeFormat(); +Object.setPrototypeOf(ccwDateTimeFormatWithPoisonedFallback, Intl.DateTimeFormat.prototype); +Object.defineProperty(ccwDateTimeFormatWithPoisonedFallback, intlFallbackSymbol, { + get() { throw new Error(); } +}); +Object.defineProperty(ccwDateTimeFormatWithPoisonedFallback, otherIntlFallbackSymbol, { + get() { throw new Error(); } +}); + +assertEq(Intl_DateTimeFormat_format_get.call(ccwDateTimeFormatWithPoisonedFallback)(0), + Intl_DateTimeFormat_format_get.call(dateTimeFormat)(0)); + +assertEq(deepEqual(Intl_DateTimeFormat_resolvedOptions.call(ccwDateTimeFormatWithPoisonedFallback), + Intl_DateTimeFormat_resolvedOptions.call(dateTimeFormat)), + true); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/dateTimeStyle.js b/js/src/tests/non262/Intl/DateTimeFormat/dateTimeStyle.js new file mode 100644 index 0000000000..1dd4c35316 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/dateTimeStyle.js @@ -0,0 +1,57 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Date style + +var dtf = new Intl.DateTimeFormat("en-US", {dateStyle: 'long'}); +assertEq(dtf.resolvedOptions().dateStyle, 'long'); +assertEq(dtf.resolvedOptions().hasOwnProperty('year'), false); +assertEq(dtf.resolvedOptions().hasOwnProperty('month'), false); +assertEq(dtf.resolvedOptions().hasOwnProperty('day'), false); + +// Time style + +var dtf = new Intl.DateTimeFormat("en-US", {timeStyle: 'long'}); +assertEq(dtf.resolvedOptions().timeStyle, 'long'); +assertEq(dtf.resolvedOptions().hasOwnProperty('hour'), false); +assertEq(dtf.resolvedOptions().hasOwnProperty('minute'), false); +assertEq(dtf.resolvedOptions().hasOwnProperty('second'), false); + +// Date/Time style + +var dtf = new Intl.DateTimeFormat("en-US", {dateStyle: 'medium', timeStyle: 'medium'}); +assertEq(dtf.resolvedOptions().timeStyle, 'medium'); +assertEq(dtf.resolvedOptions().dateStyle, 'medium'); +assertEq(dtf.resolvedOptions().hasOwnProperty('hour'), false); +assertEq(dtf.resolvedOptions().hasOwnProperty('minute'), false); +assertEq(dtf.resolvedOptions().hasOwnProperty('second'), false); +assertEq(dtf.resolvedOptions().hasOwnProperty('year'), false); +assertEq(dtf.resolvedOptions().hasOwnProperty('month'), false); +assertEq(dtf.resolvedOptions().hasOwnProperty('day'), false); + +// Error when mixing date/timeStyle with other date-time options. + +assertThrowsInstanceOf(() => { + new Intl.DateTimeFormat("en-US", {dateStyle: 'medium', year: 'numeric'}); +}, TypeError); + +assertThrowsInstanceOf(() => { + new Intl.DateTimeFormat("en-US", {timeStyle: 'medium', year: 'numeric'}); +}, TypeError); + +// Error when using dateStyle in toLocaleTimeString. + +assertThrowsInstanceOf(() => { + new Date().toLocaleTimeString("en-US", {dateStyle: 'long'}); +}, TypeError); + +// Error when using dateStyle in toLocaleDateString. + +assertThrowsInstanceOf(() => { + new Date().toLocaleDateString("en-US", {timeStyle: 'long'}); +}, TypeError); + +if (typeof reportCompare === "function") + reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/day-period-hour-cycle.js b/js/src/tests/non262/Intl/DateTimeFormat/day-period-hour-cycle.js new file mode 100644 index 0000000000..6bfbf94df3 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/day-period-hour-cycle.js @@ -0,0 +1,102 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const { + Year, Month, Day, DayPeriod, Hour, Minute, Literal +} = DateTimeFormatParts; + +// If the locale defaults to a 24-hour-cycle, the "dayPeriod" option is ignored if an "hour" option +// is also present, unless the hour-cycle is manually set to a 12-hour-cycle. + +const tests = [ + { + date: new Date("2019-01-01T12:00:00"), + options: { dayPeriod: "short", hour: "numeric", }, + locales: { + en: [Hour("12"), Literal(" "), DayPeriod("noon")], + de: [Hour("12"), Literal(" Uhr")], + }, + }, + { + date: new Date("2019-01-01T12:00:00"), + options: { dayPeriod: "short", hour: "numeric", hour12: true }, + locales: { + en: [Hour("12"), Literal(" "), DayPeriod("noon")], + de: [Hour("12"), Literal(" "), DayPeriod("mittags")], + }, + }, + { + date: new Date("2019-01-01T12:00:00"), + options: { dayPeriod: "short", hour: "numeric", hour12: false }, + locales: { + en: [Hour("12")], + de: [Hour("12"), Literal(" Uhr")], + }, + }, + { + date: new Date("2019-01-01T12:00:00"), + options: { dayPeriod: "short", hour: "numeric", hourCycle: "h12" }, + locales: { + en: [Hour("12"), Literal(" "), DayPeriod("noon")], + de: [Hour("12"), Literal(" "), DayPeriod("mittags")], + }, + }, + { + date: new Date("2019-01-01T12:00:00"), + options: { dayPeriod: "short", hour: "numeric", hourCycle: "h11" }, + locales: { + en: [Hour("0"), Literal(" "), DayPeriod("noon")], + de: [Hour("0"), Literal(" "), DayPeriod("mittags")], + }, + }, + { + date: new Date("2019-01-01T12:00:00"), + options: { dayPeriod: "short", hour: "numeric", hourCycle: "h23" }, + locales: { + en: [Hour("12")], + de: [Hour("12"), Literal(" Uhr")], + }, + }, + { + date: new Date("2019-01-01T12:00:00"), + options: { dayPeriod: "short", hour: "numeric", hourCycle: "h24" }, + locales: { + en: [Hour("12")], + de: [Hour("12"), Literal(" Uhr")], + }, + }, + + // The default hour-cycle is irrelevant when an "hour" option isn't present. + { + date: new Date("2019-01-01T12:00:00"), + options: { dayPeriod: "short", day: "numeric", month: "numeric", year: "numeric" }, + locales: { + en: [Month("1"), Literal("/"), Day("1"), Literal("/"), Year("2019"), Literal(", "), DayPeriod("noon")], + de: [Day("1"), Literal("."), Month("1"), Literal("."), Year("2019"), Literal(", "), DayPeriod("mittags")], + }, + }, + + // ICU replacement pattern for missing entries in CLDR. + { + date: new Date("2019-01-01T12:00:00"), + options: { dayPeriod: "short", minute: "numeric" }, + locales: { + en: [Minute("0"), Literal(" (AM/PM: "), DayPeriod("noon"), Literal(")")], + de: [Minute("0"), Literal(" (Tageshälfte: "), DayPeriod("mittags"), Literal(")")], + }, + }, +]; + +for (let {date, options, locales} of tests) { + for (let [locale, parts] of Object.entries(locales)) { + let dtf = new Intl.DateTimeFormat(locale, options); + + assertEq(dtf.format(date), parts.map(({value}) => value).join(""), + `locale=${locale}, date=${date}, options=${JSON.stringify(options)}`); + + assertDeepEq(dtf.formatToParts(date), parts, + `locale=${locale}, date=${date}, options=${JSON.stringify(options)}`); + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/day-period-standalone.js b/js/src/tests/non262/Intl/DateTimeFormat/day-period-standalone.js new file mode 100644 index 0000000000..203ba03766 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/day-period-standalone.js @@ -0,0 +1,160 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Tests using various locales to cover all day period types: +// "midnight", "noon", "morning1", "morning2", "afternoon1", "afternoon2", +// "evening1", "evening2", "night1", "night2". + +const tests = [ + { + // ICU doesn't support "midnight" and instead uses "night1" resp. "night2". + // ICU bug: https://unicode-org.atlassian.net/projects/ICU/issues/ICU-12278 + date: new Date("2019-01-01T00:00:00"), + locales: { + en: { narrow: "at night", short: "at night", long: "at night" }, + de: { narrow: "nachts", short: "nachts", long: "nachts" }, + th: { narrow: "กลางคืน", short: "กลางคืน", long: "กลางคืน" }, + ja: { narrow: "夜中", short: "夜中", long: "夜中" }, + } + }, + { + date: new Date("2019-01-01T03:00:00"), + locales: { + en: { narrow: "at night", short: "at night", long: "at night" }, + de: { narrow: "nachts", short: "nachts", long: "nachts" }, + th: { narrow: "กลางคืน", short: "กลางคืน", long: "กลางคืน" }, + ja: { narrow: "夜中", short: "夜中", long: "夜中" }, + } + }, + { + date: new Date("2019-01-01T04:00:00"), + locales: { + en: { narrow: "at night", short: "at night", long: "at night" }, + de: { narrow: "nachts", short: "nachts", long: "nachts" }, + th: { narrow: "กลางคืน", short: "กลางคืน", long: "กลางคืน" }, + ja: { narrow: "朝", short: "朝", long: "朝" }, + } + }, + { + date: new Date("2019-01-01T05:00:00"), + locales: { + en: { narrow: "at night", short: "at night", long: "at night" }, + de: { narrow: "morgens", short: "morgens", long: "morgens" }, + th: { narrow: "กลางคืน", short: "กลางคืน", long: "กลางคืน" }, + ja: { narrow: "朝", short: "朝", long: "朝" }, + } + }, + { + date: new Date("2019-01-01T06:00:00"), + locales: { + en: { narrow: "in the morning", short: "in the morning", long: "in the morning" }, + de: { narrow: "morgens", short: "morgens", long: "morgens" }, + th: { narrow: "เช้า", short: "ในตอนเช้า", long: "ในตอนเช้า" }, + ja: { narrow: "朝", short: "朝", long: "朝" }, + } + }, + { + date: new Date("2019-01-01T10:00:00"), + locales: { + en: { narrow: "in the morning", short: "in the morning", long: "in the morning" }, + de: { narrow: "vorm.", short: "vorm.", long: "vormittags" }, + th: { narrow: "เช้า", short: "ในตอนเช้า", long: "ในตอนเช้า" }, + ja: { narrow: "朝", short: "朝", long: "朝" }, + } + }, + { + date: new Date("2019-01-01T12:00:00"), + locales: { + en: { narrow: "n", short: "noon", long: "noon" }, + de: { narrow: "mittags", short: "mittags", long: "mittags" }, + th: { narrow: "เที่ยง", short: "เที่ยง", long: "เที่ยง" }, + ja: { narrow: "正午", short: "正午", long: "正午" }, + } + }, + { + date: new Date("2019-01-01T13:00:00"), + locales: { + en: { narrow: "in the afternoon", short: "in the afternoon", long: "in the afternoon" }, + de: { narrow: "nachm.", short: "nachm.", long: "nachmittags" }, + th: { narrow: "บ่าย", short: "บ่าย", long: "บ่าย" }, + ja: { narrow: "昼", short: "昼", long: "昼" }, + } + }, + { + date: new Date("2019-01-01T15:00:00"), + locales: { + en: { narrow: "in the afternoon", short: "in the afternoon", long: "in the afternoon" }, + de: { narrow: "nachm.", short: "nachm.", long: "nachmittags" }, + th: { narrow: "บ่าย", short: "บ่าย", long: "บ่าย" }, + ja: { narrow: "昼", short: "昼", long: "昼" }, + } + }, + { + date: new Date("2019-01-01T16:00:00"), + locales: { + en: { narrow: "in the afternoon", short: "in the afternoon", long: "in the afternoon" }, + de: { narrow: "nachm.", short: "nachm.", long: "nachmittags" }, + th: { narrow: "เย็น", short: "ในตอนเย็น", long: "ในตอนเย็น" }, + ja: { narrow: "夕方", short: "夕方", long: "夕方" }, + } + }, + { + date: new Date("2019-01-01T18:00:00"), + locales: { + en: { narrow: "in the evening", short: "in the evening", long: "in the evening" }, + de: { narrow: "abends", short: "abends", long: "abends" }, + th: { narrow: "ค่ำ", short: "ค่ำ", long: "ค่ำ" }, + ja: { narrow: "夕方", short: "夕方", long: "夕方" }, + } + }, + { + date: new Date("2019-01-01T19:00:00"), + locales: { + en: { narrow: "in the evening", short: "in the evening", long: "in the evening" }, + de: { narrow: "abends", short: "abends", long: "abends" }, + th: { narrow: "ค่ำ", short: "ค่ำ", long: "ค่ำ" }, + ja: { narrow: "夜", short: "夜", long: "夜" }, + } + }, + { + date: new Date("2019-01-01T21:00:00"), + locales: { + en: { narrow: "at night", short: "at night", long: "at night" }, + de: { narrow: "abends", short: "abends", long: "abends" }, + th: { narrow: "กลางคืน", short: "กลางคืน", long: "กลางคืน" }, + ja: { narrow: "夜", short: "夜", long: "夜" }, + } + }, + { + date: new Date("2019-01-01T22:00:00"), + locales: { + en: { narrow: "at night", short: "at night", long: "at night" }, + de: { narrow: "abends", short: "abends", long: "abends" }, + th: { narrow: "กลางคืน", short: "กลางคืน", long: "กลางคืน" }, + ja: { narrow: "夜", short: "夜", long: "夜" }, + } + }, + { + date: new Date("2019-01-01T23:00:00"), + locales: { + en: { narrow: "at night", short: "at night", long: "at night" }, + de: { narrow: "abends", short: "abends", long: "abends" }, + th: { narrow: "กลางคืน", short: "กลางคืน", long: "กลางคืน" }, + ja: { narrow: "夜中", short: "夜中", long: "夜中" }, + } + }, +]; + +for (let {date, locales} of tests) { + for (let [locale, formats] of Object.entries(locales)) { + for (let [dayPeriod, expected] of Object.entries(formats)) { + let dtf = new Intl.DateTimeFormat(locale, {dayPeriod}); + + assertEq(dtf.format(date), expected, + `locale=${locale}, date=${date}, dayPeriod=${dayPeriod}`); + assertDeepEq(dtf.formatToParts(date), [{type: "dayPeriod", value: expected}]); + } + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/day-period.js b/js/src/tests/non262/Intl/DateTimeFormat/day-period.js new file mode 100644 index 0000000000..486970e519 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/day-period.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const { + Weekday, DayPeriod, Literal +} = DateTimeFormatParts; + +const tests = [ + // https://unicode-org.atlassian.net/browse/ICU-20741 + { + date: new Date("2019-01-01T12:00:00"), + options: { dayPeriod: "long", weekday: "long", }, + locales: { + "en-001": [Weekday("Tuesday"), Literal(", "), DayPeriod("noon")], + }, + }, + + // https://unicode-org.atlassian.net/browse/ICU-20740 + { + date: new Date("2019-01-01T12:00:00"), + options: { dayPeriod: "narrow", weekday: "long", }, + locales: { + "bs-Cyrl": [Weekday("уторак"), Literal(" "), DayPeriod("подне")], + }, + }, +]; + +for (let {date, options, locales} of tests) { + for (let [locale, parts] of Object.entries(locales)) { + let dtf = new Intl.DateTimeFormat(locale, options); + + assertEq(dtf.format(date), parts.map(({value}) => value).join(""), + `locale=${locale}, date=${date}, options=${JSON.stringify(options)}`); + + assertDeepEq(dtf.formatToParts(date), parts, + `locale=${locale}, date=${date}, options=${JSON.stringify(options)}`); + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/era.js b/js/src/tests/non262/Intl/DateTimeFormat/era.js new file mode 100644 index 0000000000..716fa2cf0d --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/era.js @@ -0,0 +1,245 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const { + Era, Year, Month, Day, Literal +} = DateTimeFormatParts; + +const tests = { + "en": [ + { + options: { + day: "numeric", + month: "numeric", + year: "numeric", + era: "short", + timeZone: "UTC", + }, + dates: [ + { + date: new Date("1970-01-01T00:00:00.000Z"), + parts: [ + Month("1"), Literal("/"), Day("1"), Literal("/"), Year("1970"), Literal(" "), Era("AD") + ], + }, + { + date: new Date("-001970-01-01T00:00:00.000Z"), + parts: [ + Month("1"), Literal("/"), Day("1"), Literal("/"), Year("1971"), Literal(" "), Era("BC") + ], + }, + ], + }, + ], + "en-001": [ + { + options: { + day: "numeric", + month: "numeric", + year: "numeric", + era: "short", + timeZone: "UTC", + }, + dates: [ + { + date: new Date("1970-01-01T00:00:00.000Z"), + parts: [ + Day("1"), Literal("/"), Month("1"), Literal("/"), Year("1970"), Literal(" "), Era("AD") + ], + }, + { + date: new Date("-001970-01-01T00:00:00.000Z"), + parts: [ + Day("1"), Literal("/"), Month("1"), Literal("/"), Year("1971"), Literal(" "), Era("BC") + ], + }, + ], + }, + ], + "de": [ + { + options: { + day: "numeric", + month: "numeric", + year: "numeric", + era: "short", + timeZone: "UTC", + }, + dates: [ + { + date: new Date("1970-01-01T00:00:00.000Z"), + parts: [ + Day("01"), Literal("."), Month("01"), Literal("."), Year("1970"), Literal(" "), Era("n. Chr.") + ], + }, + { + date: new Date("-001970-01-01T00:00:00.000Z"), + parts: [ + Day("01"), Literal("."), Month("01"), Literal("."), Year("1971"), Literal(" "), Era("v. Chr.") + ], + }, + ], + }, + ], + "fr": [ + { + options: { + day: "numeric", + month: "numeric", + year: "numeric", + era: "short", + timeZone: "UTC", + }, + dates: [ + { + date: new Date("1970-01-01T00:00:00.000Z"), + parts: [ + Day("01"), Literal("/"), Month("01"), Literal("/"), Year("1970"), Literal(" "), Era("ap. J.-C.") + ], + }, + { + date: new Date("-001970-01-01T00:00:00.000Z"), + parts: [ + Day("01"), Literal("/"), Month("01"), Literal("/"), Year("1971"), Literal(" "), Era("av. J.-C.") + ], + }, + ], + }, + ], + "es": [ + { + options: { + day: "numeric", + month: "numeric", + year: "numeric", + era: "short", + timeZone: "UTC", + }, + dates: [ + { + date: new Date("1970-01-01T00:00:00.000Z"), + parts: [ + Day("1"), Literal("/"), Month("1"), Literal("/"), Year("1970"), Literal(" "), Era("d. C.") + ], + }, + { + date: new Date("-001970-01-01T00:00:00.000Z"), + parts: [ + Day("1"), Literal("/"), Month("1"), Literal("/"), Year("1971"), Literal(" "), Era("a. C.") + ], + }, + ], + }, + ], + "nl": [ + { + options: { + day: "numeric", + month: "numeric", + year: "numeric", + era: "short", + timeZone: "UTC", + }, + dates: [ + { + date: new Date("1970-01-01T00:00:00.000Z"), + parts: [ + Day("1"), Literal("/"), Month("1"), Literal("/"), Year("1970"), Literal(" "), Era("n.Chr.") + ], + }, + { + date: new Date("-001970-01-01T00:00:00.000Z"), + parts: [ + Day("1"), Literal("/"), Month("1"), Literal("/"), Year("1971"), Literal(" "), Era("v.Chr.") + ], + }, + ], + }, + ], + "ja": [ + { + options: { + day: "numeric", + month: "numeric", + year: "numeric", + era: "short", + timeZone: "UTC", + }, + dates: [ + { + date: new Date("1970-01-01T00:00:00.000Z"), + parts: [ + Era("西暦"), Year("1970"), Literal("/"), Month("1"), Literal("/"), Day("1") + ], + }, + { + date: new Date("-001970-01-01T00:00:00.000Z"), + parts: [ + Era("紀元前"), Year("1971"), Literal("/"), Month("1"), Literal("/"), Day("1") + ], + }, + ], + }, + ], + "zh": [ + { + options: { + day: "numeric", + month: "numeric", + year: "numeric", + era: "short", + timeZone: "UTC", + }, + dates: [ + { + date: new Date("1970-01-01T00:00:00.000Z"), + parts: [ + Era("公元"), Literal(" "), Year("1970"), Literal("-"), Month("01"), Literal("-"), Day("01") + ], + }, + { + date: new Date("-001970-01-01T00:00:00.000Z"), + parts: [ + Era("公元前"), Literal(" "), Year("1971"), Literal("-"), Month("01"), Literal("-"), Day("01") + ], + }, + ], + }, + ], + "ar": [ + { + options: { + day: "numeric", + month: "numeric", + year: "numeric", + era: "short", + timeZone: "UTC", + }, + dates: [ + { + date: new Date("1970-01-01T00:00:00.000Z"), + parts: [ + Day("٠١"), Literal("-"), Month("٠١"), Literal("-"), Year("١٩٧٠"), Literal(" "), Era("م") + ], + }, + { + date: new Date("-001970-01-01T00:00:00.000Z"), + parts: [ + Day("٠١"), Literal("-"), Month("٠١"), Literal("-"), Year("١٩٧١"), Literal(" "), Era("ق.م") + ], + }, + ], + }, + ], +}; + +for (let [locale, inputs] of Object.entries(tests)) { + for (let {options, dates} of inputs) { + let dtf = new Intl.DateTimeFormat(locale, options); + for (let {date, parts} of dates) { + assertParts(dtf, date, parts); + } + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/extended-time-zone-names.js b/js/src/tests/non262/Intl/DateTimeFormat/extended-time-zone-names.js new file mode 100644 index 0000000000..12090c4119 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/extended-time-zone-names.js @@ -0,0 +1,124 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const tests = { + "America/Los_Angeles": { + date: Date.UTC(2021, 5-1, 20, 12, 0, 0), + timeZoneName: "longGeneric", + locales: { + "en": "5/20/2021, Pacific Time", + "de": "20.5.2021, Nordamerikanische Westküstenzeit", + "fr": "20/05/2021 à heure du Pacifique nord-américain", + "ar": "٢٠‏/٥‏/٢٠٢١ توقيت المحيط الهادي", + "th": "20/5/2564 เวลาแปซิฟิกในอเมริกาเหนือ", + "zh": "2021/5/20 北美太平洋时间", + "ja": "2021/5/20 アメリカ太平洋時間", + } + }, + "America/Los_Angeles": { + date: Date.UTC(2021, 5-1, 20, 12, 0, 0), + timeZoneName: "shortGeneric", + locales: { + "en": "5/20/2021, PT", + "de": "20.5.2021, Los Angeles Zeit", + "fr": "20/05/2021 à heure : Los Angeles", + "ar": "٢٠‏/٥‏/٢٠٢١ توقيت Los Angeles", + "th": "20/5/2564 เวลาLos Angeles", + "zh": "2021/5/20 Los Angeles时间", + "ja": "2021/5/20 Los Angeles時間", + } + }, + "America/Los_Angeles": { + date: Date.UTC(2021, 5-1, 20, 12, 0, 0), + timeZoneName: "longOffset", + locales: { + "en": "5/20/2021, GMT-07:00", + "de": "20.5.2021, GMT-07:00", + "fr": "20/05/2021 à UTC−07:00", + "ar": "٢٠‏/٥‏/٢٠٢١ غرينتش-٠٧:٠٠", + "th": "20/5/2564 GMT-07:00", + "zh": "2021/5/20 GMT-07:00", + "ja": "2021/5/20 GMT-07:00", + } + }, + "America/Los_Angeles": { + date: Date.UTC(2021, 5-1, 20, 12, 0, 0), + timeZoneName: "shortOffset", + locales: { + "en": "5/20/2021, GMT-7", + "de": "20.5.2021, GMT-7", + "fr": "20/05/2021 UTC−7", + "ar": "٢٠‏/٥‏/٢٠٢١، غرينتش-٧", + "th": "20/5/2564 GMT-7", + "zh": "2021/5/20 GMT-7", + "ja": "2021/5/20 GMT-7", + } + }, + "Europe/Berlin": { + date: Date.UTC(2021, 5-1, 20, 12, 0, 0), + timeZoneName: "longGeneric", + locales: { + "en": "5/20/2021, Central European Time", + "de": "20.5.2021, Mitteleuropäische Zeit", + "fr": "20/05/2021 à heure d’Europe centrale", + "ar": "٢٠‏/٥‏/٢٠٢١ توقيت وسط أوروبا", + "th": "20/5/2564 เวลายุโรปกลาง", + "zh": "2021/5/20 中欧时间", + "ja": "2021/5/20 中央ヨーロッパ時間", + } + }, + "Europe/Berlin": { + date: Date.UTC(2021, 5-1, 20, 12, 0, 0), + timeZoneName: "shortGeneric", + locales: { + "en": "5/20/2021, Germany Time", + "de": "20.5.2021, MEZ", + "fr": "20/05/2021 heure : Allemagne", + "ar": "٢٠‏/٥‏/٢٠٢١، توقيت ألمانيا", + "th": "20/5/2564 เวลาเยอรมนี", + "zh": "2021/5/20 德国时间", + "ja": "2021/5/20 ドイツ時間", + } + }, + "Africa/Monrovia": { + date: Date.UTC(1971, 12-1, 6, 12, 0, 0), + timeZoneName: "longOffset", + locales: { + "en": "12/6/1971, GMT-00:44:30", + "de": "6.12.1971, GMT-00:44:30", + "fr": "06/12/1971 UTC−00:44:30", + "ar": "٦‏/١٢‏/١٩٧١ غرينتش-٠٠:٤٤:٣٠", + "th": "6/12/2514 GMT-00:44:30", + "zh": "1971/12/6 GMT-00:44:30", + "ja": "1971/12/6 GMT-00:44:30", + } + }, + "Africa/Monrovia": { + date: Date.UTC(1971, 12-1, 6, 12, 0, 0), + timeZoneName: "shortOffset", + locales: { + "en": "12/6/1971, GMT-0:44:30", + "de": "6.12.1971, GMT-0:44:30", + "fr": "06/12/1971 UTC−0:44:30", + "ar": "٦‏/١٢‏/١٩٧١، غرينتش-٠:٤٤:٣٠", + "th": "6/12/2514 GMT-0:44:30", + "zh": "1971/12/6 GMT-0:44:30", + "ja": "1971/12/6 GMT-0:44:30", + } + }, +}; + +for (let [timeZone, {timeZoneName, date, locales}] of Object.entries(tests)) { + for (let [locale, expected] of Object.entries(locales)) { + let dtf = new Intl.DateTimeFormat(locale, {timeZone, timeZoneName}); + assertEq(dtf.format(date), expected); + + let parts = dtf.formatToParts(date); + assertEq(parts.map(p => p.value).join(""), expected); + assertEq(parts.filter(p => p.type === "timeZoneName").length, 1); + + assertEq(dtf.resolvedOptions().timeZoneName, timeZoneName); + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/field-widths.js b/js/src/tests/non262/Intl/DateTimeFormat/field-widths.js new file mode 100644 index 0000000000..789d0fdaa6 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/field-widths.js @@ -0,0 +1,225 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const date = new Date(Date.UTC(2021, 1-1, 2, 3, 4, 5, 678)); + +const tests = [ + // Standalone 'hour' field. + { + options: { + hour: "numeric", + }, + locales: { + "en": "3 AM", + "de": "03 Uhr", + }, + }, + { + options: { + hour: "2-digit", + }, + locales: { + "en": "03 AM", + "de": "03 Uhr", + }, + }, + + // Standalone 'minute' field. + { + options: { + minute: "numeric", + }, + locales: { + "en": "4", + "de": "4", + }, + }, + { + options: { + minute: "2-digit", + }, + locales: { + "en": "04", + "de": "04", + }, + }, + + // Standalone 'second' field. + { + options: { + second: "numeric", + }, + locales: { + "en": "5", + "de": "5", + }, + }, + { + options: { + second: "2-digit", + }, + locales: { + "en": "05", + "de": "05", + }, + }, + + // 'hour' and 'minute' fields with all possible field width combinations. + { + options: { + hour: "numeric", + minute: "numeric", + }, + locales: { + "en": "3:04 AM", + "de": "03:04", + }, + }, + { + options: { + hour: "numeric", + minute: "2-digit", + }, + locales: { + "en": "3:04 AM", + "de": "03:04", + }, + }, + { + options: { + hour: "2-digit", + minute: "numeric", + }, + locales: { + "en": "03:04 AM", + "de": "03:04", + }, + }, + { + options: { + hour: "2-digit", + minute: "2-digit", + }, + locales: { + "en": "03:04 AM", + "de": "03:04", + }, + }, + + // 'minute' and 'second' fields with all possible field width combinations. + { + options: { + minute: "numeric", + second: "numeric", + }, + locales: { + "en": "04:05", + "de": "04:05", + }, + }, + { + options: { + minute: "numeric", + second: "2-digit", + }, + locales: { + "en": "04:05", + "de": "04:05", + }, + }, + { + options: { + minute: "2-digit", + second: "numeric", + }, + locales: { + "en": "04:05", + "de": "04:05", + }, + }, + { + options: { + minute: "2-digit", + second: "2-digit", + }, + locales: { + "en": "04:05", + "de": "04:05", + }, + }, + + // Test 'hour' and 'minute' with 'hourCycle=h12'. + { + options: { + hour: "numeric", + minute: "numeric", + hourCycle: "h12", + }, + locales: { + "en": "3:04 AM", + "de": "3:04 AM", + }, + }, + { + options: { + hour: "2-digit", + minute: "2-digit", + hourCycle: "h12", + }, + locales: { + "en": "03:04 AM", + "de": "03:04 AM", + }, + }, + + // Test 'hour' and 'minute' with 'hourCycle=h23'. + { + options: { + hour: "numeric", + minute: "numeric", + hourCycle: "h23", + }, + locales: { + "en": "03:04", + "de": "03:04", + }, + }, + { + options: { + hour: "2-digit", + minute: "2-digit", + hourCycle: "h23", + }, + locales: { + "en": "03:04", + "de": "03:04", + }, + }, +]; + +for (let {options, locales} of tests) { + for (let [locale, expected] of Object.entries(locales)) { + let dtf = new Intl.DateTimeFormat(locale, {timeZone: "UTC", ...options}); + assertEq(dtf.format(date), expected); + } +} + +const toLocaleTests = { + "en": "1/2/2021, 3:04:05 AM", + "de": "2.1.2021, 03:04:05", +}; + +for (let [locale, expected] of Object.entries(toLocaleTests)) { + assertEq(date.toLocaleString(locale, {timeZone: "UTC"}), expected); +} + +const toLocaleTimeTests = { + "en": "3:04:05 AM", + "de": "03:04:05", +}; + +for (let [locale, expected] of Object.entries(toLocaleTimeTests)) { + assertEq(date.toLocaleTimeString(locale, {timeZone: "UTC"}), expected); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/format-timeZone-offset.js b/js/src/tests/non262/Intl/DateTimeFormat/format-timeZone-offset.js new file mode 100644 index 0000000000..ed28a52c69 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/format-timeZone-offset.js @@ -0,0 +1,109 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const { + Hour, Minute, Literal, TimeZoneName, +} = DateTimeFormatParts; + +const tests = { + "en": [ + { + date: 0, + timeZone: "-23", + options: {hour: "numeric", minute: "numeric", hour12: false}, + timeZoneNames: { + short: [Hour("01"), Literal(":"), Minute("00"), Literal(" "), TimeZoneName("GMT-23")], + shortOffset: "short", + shortGeneric: "short", + long: [Hour("01"), Literal(":"), Minute("00"), Literal(" "), TimeZoneName("GMT-23:00")], + longOffset: "long", + longGeneric: "long", + }, + }, + { + date: 0, + timeZone: "+23:59", + options: {hour: "numeric", minute: "numeric", hour12: false}, + timeZoneNames: { + short: [Hour("23"), Literal(":"), Minute("59"), Literal(" "), TimeZoneName("GMT+23:59")], + shortOffset: "short", + shortGeneric: "short", + long: [Hour("23"), Literal(":"), Minute("59"), Literal(" "), TimeZoneName("GMT+23:59")], + longOffset: "long", + longGeneric: "long", + }, + }, + ], + "fr": [ + { + date: 0, + timeZone: "-23", + options: {hour: "numeric", minute: "numeric", hour12: false}, + timeZoneNames: { + short: [Hour("01"), Literal(":"), Minute("00"), Literal(" "), TimeZoneName("UTC\u{2212}23")], + shortOffset: "short", + shortGeneric: "short", + long: [Hour("01"), Literal(":"), Minute("00"), Literal(" "), TimeZoneName("UTC\u{2212}23:00")], + longOffset: "long", + longGeneric: "long", + }, + }, + { + date: 0, + timeZone: "+23:59", + options: {hour: "numeric", minute: "numeric", hour12: false}, + timeZoneNames: { + short: [Hour("23"), Literal(":"), Minute("59"), Literal(" "), TimeZoneName("UTC+23:59")], + shortOffset: "short", + shortGeneric: "short", + long: [Hour("23"), Literal(":"), Minute("59"), Literal(" "), TimeZoneName("UTC+23:59")], + longOffset: "long", + longGeneric: "long", + }, + }, + ], + "ar": [ + { + date: 0, + timeZone: "+13:37", + options: {hour: "numeric", minute: "numeric", hour12: false}, + timeZoneNames: { + short: [Hour("١٣"), Literal(":"), Minute("٣٧"), Literal(" "), TimeZoneName("غرينتش+١٣:٣٧")], + shortOffset: "short", + shortGeneric: "short", + long: "short", + longOffset: "short", + longGeneric: "short", + }, + }, + ], + "zh": [ + { + date: 0, + timeZone: "+23:59", + options: {hour: "numeric", minute: "numeric", hour12: false}, + timeZoneNames: { + short: [TimeZoneName("GMT+23:59"), Literal(" "), Hour("23"), Literal(":"), Minute("59")], + shortOffset: "short", + shortGeneric: "short", + long: "short", + longOffset: "short", + longGeneric: "short", + }, + }, + ], +}; + +for (let [locale, formats] of Object.entries(tests)) { + for (let {date, timeZone, options, timeZoneNames} of formats) { + for (let [timeZoneName, format] of Object.entries(timeZoneNames)) { + let df = new Intl.DateTimeFormat(locale, {timeZone, timeZoneName, ...options}); + if (typeof format === "string") { + format = timeZoneNames[format]; + } + assertParts(df, date, format); + } + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/format.js b/js/src/tests/non262/Intl/DateTimeFormat/format.js new file mode 100644 index 0000000000..224d19cfa8 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/format.js @@ -0,0 +1,47 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Tests the format function with a diverse set of locales and options. +// Always use UTC to avoid dependencies on test environment. + +var format; +var date = Date.UTC(2012, 11, 12, 3, 0, 0); +var longFormatOptions = {timeZone: "UTC", + year: "numeric", month: "long", day: "numeric", + hour: "numeric", minute: "numeric", second: "numeric"}; + +// Locale en-US; default options. +format = new Intl.DateTimeFormat("en-us", {timeZone: "UTC"}); +assertEq(format.format(date), "12/12/2012"); + +// Locale th-TH; default options. +// Thailand uses the Buddhist calendar. +format = new Intl.DateTimeFormat("th-th", {timeZone: "UTC"}); +assertEq(format.format(date), "12/12/2555"); + +// Locale th-TH; long format, Thai digits. +format = new Intl.DateTimeFormat("th-th-u-nu-thai", longFormatOptions); +assertEq(format.format(date), "๑๒ ธันวาคม ๒๕๕๕ เวลา ๐๓:๐๐:๐๐"); + +// Locale ja-JP; long format. +format = new Intl.DateTimeFormat("ja-jp", longFormatOptions); +assertEq(format.format(date), "2012年12月12日 3:00:00"); + +// Locale ar-MA; long format, Islamic civilian calendar. +format = new Intl.DateTimeFormat("ar-ma-u-ca-islamicc", longFormatOptions); +assertEq(format.format(date), "28 محرم 1434 هـ في 03:00:00"); + +// Locale en-IE: timeZoneName for crash test +format = new Intl.DateTimeFormat("en-IE", {timeZone: "UTC", timeZoneName: "short"}); +assertEq(format.format(date), "12/12/2012, UTC"); + +// Test the .name property of the "format" getter. +var desc = Object.getOwnPropertyDescriptor(Intl.DateTimeFormat.prototype, "format"); +assertEq(desc !== undefined, true); +assertEq(typeof desc.get, "function"); +assertEq(desc.get.name, "get format"); + + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/formatRange-gregorian-proleptic.js b/js/src/tests/non262/Intl/DateTimeFormat/formatRange-gregorian-proleptic.js new file mode 100644 index 0000000000..9356577b47 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/formatRange-gregorian-proleptic.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Ensure formatRange() uses a proleptic Gregorian calendar. +// ICU bug: https://unicode-org.atlassian.net/browse/ICU-20705 + +let dtf = new Intl.DateTimeFormat("en", {timeZone: "UTC"}); + +// The Gregorian calendar was first introduced in 15 October 1582. +const firstGregorian = new Date("1582-10-15"); +assertEq(dtf.formatRange(firstGregorian, firstGregorian), dtf.format(firstGregorian)); + +// To deal with the ten days' difference between the Julian and the Gregorian calendar, some days +// were skipped, so that 4 October 1582 was followed by 15 October 1582. +const lastJulian = new Date("1582-10-04"); +assertEq(dtf.formatRange(lastJulian, lastJulian), dtf.format(lastJulian)); + +function rangePart(source, parts) { + return parts.filter(x => x.source === source).map(x => x.value).join(""); +} + +// Test with non-empty range. +assertEq(rangePart("startRange", dtf.formatRangeToParts(lastJulian, firstGregorian)), + dtf.format(lastJulian)); +assertEq(rangePart("endRange", dtf.formatRangeToParts(lastJulian, firstGregorian)), + dtf.format(firstGregorian)); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/formatRange-hour-cycle.js b/js/src/tests/non262/Intl/DateTimeFormat/formatRange-hour-cycle.js new file mode 100644 index 0000000000..7921f502cc --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/formatRange-hour-cycle.js @@ -0,0 +1,450 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Test formatRange supports the different hour-cycle options. +// +// ICU bugs: +// https://unicode-org.atlassian.net/browse/ICU-21154 +// https://unicode-org.atlassian.net/browse/ICU-21155 +// https://unicode-org.atlassian.net/browse/ICU-21156 +// https://unicode-org.atlassian.net/browse/ICU-21342 +// https://unicode-org.atlassian.net/browse/ICU-21343 + +// Test locales which default to a 12-hour and a 24-hour clock. + +let tests = { + "en": [ + // Midnight to morning. + { + start: 0, + end: 10, + data: [ + "12 – 10 AM", + "0 – 10 AM", + "12 – 10 AM", + "00 – 10", + "24 – 10", + ], + }, + // Midnight to noon. + { + start: 0, + end: 12, + data: [ + "12 AM – 12 PM", + "0 AM – 0 PM", + "12 AM – 12 PM", + "00 – 12", + "24 – 12", + ], + }, + // Midnight to evening. + { + start: 0, + end: 22, + data: [ + "12 AM – 10 PM", + "0 AM – 10 PM", + "12 AM – 10 PM", + "00 – 22", + "24 – 22", + ], + }, + // Midnight to midnight. + { + start: 0, + end: 24, + data: [ + "1/1/1970, 12 AM – 1/2/1970, 12 AM", + "1/1/1970, 0 AM – 1/2/1970, 0 AM", + "1/1/1970, 12 AM – 1/2/1970, 12 AM", + "1/1/1970, 00 – 1/2/1970, 00", + "1/1/1970, 24 – 1/2/1970, 24", + ], + }, + + // Morning to morning. + { + start: 1, + end: 10, + data: [ + "1 – 10 AM", + "1 – 10 AM", + "1 – 10 AM", + "01 – 10", + "01 – 10", + ], + }, + // Morning to noon. + { + start: 1, + end: 12, + data: [ + "1 AM – 12 PM", + "1 AM – 0 PM", + "1 AM – 12 PM", + "01 – 12", + "01 – 12", + ], + }, + // Morning to evening. + { + start: 1, + end: 22, + data: [ + "1 AM – 10 PM", + "1 AM – 10 PM", + "1 AM – 10 PM", + "01 – 22", + "01 – 22", + ], + }, + // Morning to midnight. + { + start: 1, + end: 24, + data: [ + "1/1/1970, 1 AM – 1/2/1970, 12 AM", + "1/1/1970, 1 AM – 1/2/1970, 0 AM", + "1/1/1970, 1 AM – 1/2/1970, 12 AM", + "1/1/1970, 01 – 1/2/1970, 00", + "1/1/1970, 01 – 1/2/1970, 24", + ], + }, + + // Noon to morning. + { + start: 12, + end: 24 + 1, + data: [ + "1/1/1970, 12 PM – 1/2/1970, 1 AM", + "1/1/1970, 0 PM – 1/2/1970, 1 AM", + "1/1/1970, 12 PM – 1/2/1970, 1 AM", + "1/1/1970, 12 – 1/2/1970, 01", + "1/1/1970, 12 – 1/2/1970, 01", + ], + }, + // Noon to noon. + { + start: 12, + end: 24 + 12, + data: [ + "1/1/1970, 12 PM – 1/2/1970, 12 PM", + "1/1/1970, 0 PM – 1/2/1970, 0 PM", + "1/1/1970, 12 PM – 1/2/1970, 12 PM", + "1/1/1970, 12 – 1/2/1970, 12", + "1/1/1970, 12 – 1/2/1970, 12", + ], + }, + // Noon to evening. + { + start: 12, + end: 22, + data: [ + "12 – 10 PM", + "0 – 10 PM", + "12 – 10 PM", + "12 – 22", + "12 – 22", + ], + }, + // Noon to midnight. + { + start: 12, + end: 24, + data: [ + "1/1/1970, 12 PM – 1/2/1970, 12 AM", + "1/1/1970, 0 PM – 1/2/1970, 0 AM", + "1/1/1970, 12 PM – 1/2/1970, 12 AM", + "1/1/1970, 12 – 1/2/1970, 00", + "1/1/1970, 12 – 1/2/1970, 24", + ], + }, + + // Evening to morning. + { + start: 22, + end: 24 + 1, + data: [ + "1/1/1970, 10 PM – 1/2/1970, 1 AM", + "1/1/1970, 10 PM – 1/2/1970, 1 AM", + "1/1/1970, 10 PM – 1/2/1970, 1 AM", + "1/1/1970, 22 – 1/2/1970, 01", + "1/1/1970, 22 – 1/2/1970, 01", + ], + }, + // Evening to noon. + { + start: 22, + end: 24 + 12, + data: [ + "1/1/1970, 10 PM – 1/2/1970, 12 PM", + "1/1/1970, 10 PM – 1/2/1970, 0 PM", + "1/1/1970, 10 PM – 1/2/1970, 12 PM", + "1/1/1970, 22 – 1/2/1970, 12", + "1/1/1970, 22 – 1/2/1970, 12", + ], + }, + // Evening to evening. + { + start: 22, + end: 23, + data: [ + "10 – 11 PM", + "10 – 11 PM", + "10 – 11 PM", + "22 – 23", + "22 – 23", + ], + }, + // Evening to midnight. + { + start: 22, + end: 24, + data: [ + "1/1/1970, 10 PM – 1/2/1970, 12 AM", + "1/1/1970, 10 PM – 1/2/1970, 0 AM", + "1/1/1970, 10 PM – 1/2/1970, 12 AM", + "1/1/1970, 22 – 1/2/1970, 00", + "1/1/1970, 22 – 1/2/1970, 24", + ], + }, + ], + + "de": [ + // Midnight to morning. + { + start: 0, + end: 10, + data: [ + "00–10 Uhr", + "0 – 10 Uhr AM", + "12 – 10 Uhr AM", + "00–10 Uhr", + "24–10 Uhr", + ], + }, + // Midnight to noon. + { + start: 0, + end: 12, + data: [ + "00–12 Uhr", + "0 Uhr AM – 0 Uhr PM", + "12 Uhr AM – 12 Uhr PM", + "00–12 Uhr", + "24–12 Uhr", + ], + }, + // Midnight to evening. + { + start: 0, + end: 22, + data: [ + "00–22 Uhr", + "0 Uhr AM – 10 Uhr PM", + "12 Uhr AM – 10 Uhr PM", + "00–22 Uhr", + "24–22 Uhr", + ], + }, + // Midnight to midnight. + { + start: 0, + end: 24, + data: [ + "1.1.1970, 00 Uhr – 2.1.1970, 00 Uhr", + "1.1.1970, 0 Uhr AM – 2.1.1970, 0 Uhr AM", + "1.1.1970, 12 Uhr AM – 2.1.1970, 12 Uhr AM", + "1.1.1970, 00 Uhr – 2.1.1970, 00 Uhr", + "1.1.1970, 24 Uhr – 2.1.1970, 24 Uhr", + ], + }, + + // Morning to morning. + { + start: 1, + end: 10, + data: [ + "01–10 Uhr", + "1 – 10 Uhr AM", + "1 – 10 Uhr AM", + "01–10 Uhr", + "01–10 Uhr", + ], + }, + // Morning to noon. + { + start: 1, + end: 12, + data: [ + "01–12 Uhr", + "1 Uhr AM – 0 Uhr PM", + "1 Uhr AM – 12 Uhr PM", + "01–12 Uhr", + "01–12 Uhr", + ], + }, + // Morning to evening. + { + start: 1, + end: 22, + data: [ + "01–22 Uhr", + "1 Uhr AM – 10 Uhr PM", + "1 Uhr AM – 10 Uhr PM", + "01–22 Uhr", + "01–22 Uhr", + ], + }, + // Morning to midnight. + { + start: 1, + end: 24, + data: [ + "1.1.1970, 01 Uhr – 2.1.1970, 00 Uhr", + "1.1.1970, 1 Uhr AM – 2.1.1970, 0 Uhr AM", + "1.1.1970, 1 Uhr AM – 2.1.1970, 12 Uhr AM", + "1.1.1970, 01 Uhr – 2.1.1970, 00 Uhr", + "1.1.1970, 01 Uhr – 2.1.1970, 24 Uhr", + ], + }, + + // Noon to morning. + { + start: 12, + end: 24 + 1, + data: [ + "1.1.1970, 12 Uhr – 2.1.1970, 01 Uhr", + "1.1.1970, 0 Uhr PM – 2.1.1970, 1 Uhr AM", + "1.1.1970, 12 Uhr PM – 2.1.1970, 1 Uhr AM", + "1.1.1970, 12 Uhr – 2.1.1970, 01 Uhr", + "1.1.1970, 12 Uhr – 2.1.1970, 01 Uhr", + ], + }, + // Noon to noon. + { + start: 12, + end: 24 + 12, + data: [ + "1.1.1970, 12 Uhr – 2.1.1970, 12 Uhr", + "1.1.1970, 0 Uhr PM – 2.1.1970, 0 Uhr PM", + "1.1.1970, 12 Uhr PM – 2.1.1970, 12 Uhr PM", + "1.1.1970, 12 Uhr – 2.1.1970, 12 Uhr", + "1.1.1970, 12 Uhr – 2.1.1970, 12 Uhr", + ], + }, + // Noon to evening. + { + start: 12, + end: 22, + data: [ + "12–22 Uhr", + "0 – 10 Uhr PM", + "12 – 10 Uhr PM", + "12–22 Uhr", + "12–22 Uhr", + ], + }, + // Noon to midnight. + { + start: 12, + end: 24, + data: [ + "1.1.1970, 12 Uhr – 2.1.1970, 00 Uhr", + "1.1.1970, 0 Uhr PM – 2.1.1970, 0 Uhr AM", + "1.1.1970, 12 Uhr PM – 2.1.1970, 12 Uhr AM", + "1.1.1970, 12 Uhr – 2.1.1970, 00 Uhr", + "1.1.1970, 12 Uhr – 2.1.1970, 24 Uhr", + ], + }, + + // Evening to morning. + { + start: 22, + end: 24 + 1, + data: [ + "1.1.1970, 22 Uhr – 2.1.1970, 01 Uhr", + "1.1.1970, 10 Uhr PM – 2.1.1970, 1 Uhr AM", + "1.1.1970, 10 Uhr PM – 2.1.1970, 1 Uhr AM", + "1.1.1970, 22 Uhr – 2.1.1970, 01 Uhr", + "1.1.1970, 22 Uhr – 2.1.1970, 01 Uhr", + ], + }, + // Evening to noon. + { + start: 22, + end: 24 + 12, + data: [ + "1.1.1970, 22 Uhr – 2.1.1970, 12 Uhr", + "1.1.1970, 10 Uhr PM – 2.1.1970, 0 Uhr PM", + "1.1.1970, 10 Uhr PM – 2.1.1970, 12 Uhr PM", + "1.1.1970, 22 Uhr – 2.1.1970, 12 Uhr", + "1.1.1970, 22 Uhr – 2.1.1970, 12 Uhr", + ], + }, + // Evening to evening. + { + start: 22, + end: 23, + data: [ + "22–23 Uhr", + "10 – 11 Uhr PM", + "10 – 11 Uhr PM", + "22–23 Uhr", + "22–23 Uhr", + ], + }, + // Evening to midnight. + { + start: 22, + end: 24, + data: [ + "1.1.1970, 22 Uhr – 2.1.1970, 00 Uhr", + "1.1.1970, 10 Uhr PM – 2.1.1970, 0 Uhr AM", + "1.1.1970, 10 Uhr PM – 2.1.1970, 12 Uhr AM", + "1.1.1970, 22 Uhr – 2.1.1970, 00 Uhr", + "1.1.1970, 22 Uhr – 2.1.1970, 24 Uhr", + ], + }, + ], +}; + +const hourCycles = [undefined, "h11", "h12", "h23", "h24"]; +const hour12Values = [true, false]; +const options = {hour: "2-digit", timeZone: "UTC"}; +const hourToMillis = 60 * 60 * 1000; + +for (let [locale, test] of Object.entries(tests)) { + // Find the matching hourCycle for each hour12 value. + let hour12Cycles = hour12Values.map(hour12 => { + let {hourCycle} = new Intl.DateTimeFormat(locale, {...options, hour12}).resolvedOptions(); + return hourCycles.indexOf(hourCycle); + }); + + for (let {start, end, data} of Object.values(test)) { + assertEq(data.length, hourCycles.length); + + // Test all possible "hourCycle" values, including |undefined|. + for (let i = 0; i < hourCycles.length; i++) { + let hourCycle = hourCycles[i]; + let expected = data[i]; + let dtf = new Intl.DateTimeFormat(locale, {...options, hourCycle}); + + assertEq(dtf.formatRange(start * hourToMillis, end * hourToMillis), expected, + `hourCycle: ${hourCycle}`); + } + + // Test all possible "hour12" values. + for (let i = 0; i < hour12Values.length; i++) { + let hour12 = hour12Values[i]; + let dtf = new Intl.DateTimeFormat(locale, {...options, hour12}); + let expected = data[hour12Cycles[i]]; + + assertEq(dtf.formatRange(start * hourToMillis, end * hourToMillis), expected, + `hour12: ${hour12}`); + } + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/formatRange-matches-format-output.js b/js/src/tests/non262/Intl/DateTimeFormat/formatRange-matches-format-output.js new file mode 100644 index 0000000000..67cebd1843 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/formatRange-matches-format-output.js @@ -0,0 +1,58 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// formatRange() returns the same output as format() when the date-time difference between +// the start and end date is too small. + +// Test case when skeleton can't be retrieved from resolved pattern (bug 1298794). +// - Best-fit pattern for the skeleton "MMMMMdd" is "M月dd日". +// - Best-fit pattern for the skeleton "Mdd" is "M/dd". +// +// So in both cases the skeleton characters in the pattern are "Mdd", which means we can't +// retrieve the original input skeleton by simply inspecting the resolved pattern. +// +// Also see: https://unicode-org.atlassian.net/browse/ICU-13518 +{ + let dtf = new Intl.DateTimeFormat("zh", {month: "narrow", day: "2-digit", timeZone: "UTC"}); + assertEq(dtf.formatRange(0, 0), dtf.format(0)); +} + +// Test that date-/time-style leads to the same output. +// ICU bug: https://unicode-org.atlassian.net/browse/ICU-20710 +{ + let dtf = new Intl.DateTimeFormat("en", {dateStyle: "full", timeStyle: "full"}); + assertEq(dtf.formatRange(0, 0), dtf.format(0)); +} + +// Test that the hourCycle option is correctly processed (test with h24). +// ICU bug: https://unicode-org.atlassian.net/browse/ICU-20707 +{ + let dtf = new Intl.DateTimeFormat("en-u-hc-h24", {hour: "2-digit", timeZone:"UTC"}); + assertEq(dtf.formatRange(0, 0), dtf.format(0)); +} +{ + let dtf = new Intl.DateTimeFormat("en", {hourCycle: "h24", hour: "2-digit", timeZone:"UTC"}); + assertEq(dtf.formatRange(0, 0), dtf.format(0)); +} + +// Test that the hourCycle option is correctly processed (test with h11). +// ICU bug: https://unicode-org.atlassian.net/browse/ICU-20707 +{ + let dt = 60 * 60 * 1000; // one hour + let dtf = new Intl.DateTimeFormat("en-u-hc-h11", {hour: "2-digit", timeZone:"UTC"}); + assertEq(dtf.formatRange(dt, dt), dtf.format(dt)); +} +{ + let dt = 60 * 60 * 1000; // one hour + let dtf = new Intl.DateTimeFormat("en", {hourCycle: "h11", hour: "2-digit", timeZone:"UTC"}); + assertEq(dtf.formatRange(dt, dt), dtf.format(dt)); +} + +// Test that non-default calendars work correctly. +// ICU bug: https://unicode-org.atlassian.net/browse/ICU-20706 +{ + let dtf = new Intl.DateTimeFormat("en-001-u-ca-hebrew"); + assertEq(dtf.formatRange(0, 0), dtf.format(0)); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/formatRange-original-skeleton.js b/js/src/tests/non262/Intl/DateTimeFormat/formatRange-original-skeleton.js new file mode 100644 index 0000000000..c24598794e --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/formatRange-original-skeleton.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Test that the interval formatting uses the original skeleton, not the skeleton +// derived from the resolved pattern. +{ + let dtf = new Intl.DateTimeFormat("zh-Hans-CN", { + formatMatcher: "best fit", + month: "narrow", + day: "2-digit", + timeZone: "UTC" + }); + + assertEq(dtf.format(Date.UTC(2016, 7, 1)), "8月01日"); + assertEq(dtf.formatRange(Date.UTC(2016, 7, 1), Date.UTC(2016, 7, 2)), "8月1日至2日"); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/formatRange-timeZone-offset.js b/js/src/tests/non262/Intl/DateTimeFormat/formatRange-timeZone-offset.js new file mode 100644 index 0000000000..b873e081cc --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/formatRange-timeZone-offset.js @@ -0,0 +1,77 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const { + Hour, Minute, Literal, TimeZoneName, +} = DateTimeFormatParts; + +function hours(v) { + return v * 60 * 60 * 1000; +} + +function minutes(v) { + return v * 60 * 1000; +} + +const tests = { + "en": [ + { + start: 0, + end: minutes(2), + timeZone: "+00", + options: {hour: "numeric", minute: "numeric", hour12: false}, + timeZoneNames: { + short: [Hour("00"), Literal(":"), Minute("00"), Literal(" – "), Hour("00"), Literal(":"), Minute("02"), Literal(" "), TimeZoneName("GMT")], + shortOffset: "short", + shortGeneric: "short", + long: [Hour("00"), Literal(":"), Minute("00"), Literal(" – "), Hour("00"), Literal(":"), Minute("02"), Literal(" "), TimeZoneName("Greenwich Mean Time")], + longOffset: "short", + longGeneric: "long", + }, + }, + { + start: 0, + end: minutes(2), + timeZone: "-20:01", + options: {hour: "numeric", minute: "numeric", hour12: false}, + timeZoneNames: { + short: [Hour("03"), Literal(":"), Minute("59"), Literal(" – "), Hour("04"), Literal(":"), Minute("01"), Literal(" "), TimeZoneName("GMT-20:01")], + shortOffset: "short", + shortGeneric: "short", + long: "short", + longOffset: "short", + longGeneric: "short", + }, + }, + ], + "fr": [ + { + start: 0, + end: hours(2), + timeZone: "+17", + options: {hour: "numeric", hour12: false}, + timeZoneNames: { + short: [Hour("17"), Literal(" – "), Hour("19"), Literal(" "), TimeZoneName("UTC+17")], + shortOffset: "short", + shortGeneric: "short", + long: [Hour("17"), Literal(" – "), Hour("19"), Literal(" "), TimeZoneName("UTC+17:00")], + longOffset: "long", + longGeneric: "long", + }, + }, + ], +}; + +for (let [locale, formats] of Object.entries(tests)) { + for (let {start, end, timeZone, options, timeZoneNames} of formats) { + for (let [timeZoneName, format] of Object.entries(timeZoneNames)) { + let df = new Intl.DateTimeFormat(locale, {timeZone, timeZoneName, ...options}); + if (typeof format === "string") { + format = timeZoneNames[format]; + } + assertRangeParts(df, start, end, format); + } + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/formatRange-timeZoneName-matches-format.js b/js/src/tests/non262/Intl/DateTimeFormat/formatRange-timeZoneName-matches-format.js new file mode 100644 index 0000000000..028782c968 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/formatRange-timeZoneName-matches-format.js @@ -0,0 +1,45 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Test DateTimeFormat.prototype.format and DateTimeFormat.prototype.formatRange +// use the same formatting for the "timeZoneName" option. + +function hours(v) { + return v * 60 * 60 * 1000; +} + +const locales = [ + "en", "fr", "de", "es", + "ja", "th", "zh", "ar", +]; + +const timeZones = [ + "UTC", "Etc/GMT-1", "Etc/GMT+1", + "Africa/Cairo", + "America/New_York", "America/Los_Angeles", + "Asia/Riyadh", "Asia/Bangkok", "Asia/Shanghai", "Asia/Tokyo", + "Europe/Berlin", "Europe/London", "Europe/Madrid", "Europe/Paris", +]; + +const timeZoneNames = [ + "short", "shortOffset", "shortGeneric", + "long", "longOffset", "longGeneric", +]; + +function timeZonePart(parts) { + return parts.filter(({type}) => type === "timeZoneName").map(({value}) => value)[0]; +} + +for (let locale of locales) { + for (let timeZone of timeZones) { + for (let timeZoneName of timeZoneNames) { + let dtf = new Intl.DateTimeFormat(locale, {timeZone, timeZoneName, hour: "numeric"}); + + let formatTimeZone = timeZonePart(dtf.formatToParts(0)); + let formatRangeTimeZone = timeZonePart(dtf.formatRangeToParts(0, hours(1))); + assertEq(formatRangeTimeZone, formatTimeZone); + } + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/formatRange-timeZoneName.js b/js/src/tests/non262/Intl/DateTimeFormat/formatRange-timeZoneName.js new file mode 100644 index 0000000000..c99799d487 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/formatRange-timeZoneName.js @@ -0,0 +1,124 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Test all "timeZoneName" options with various locales when formatting a +// date-time range. + +const { + Hour, Minute, Literal, TimeZoneName, +} = DateTimeFormatParts; + +function hours(v) { + return v * 60 * 60 * 1000; +} + +function minutes(v) { + return v * 60 * 1000; +} + +const tests = { + "en": [ + { + start: 0, + end: minutes(2), + timeZone: "UTC", + options: {hour: "numeric", minute: "numeric", hour12: false}, + timeZoneNames: { + short: [Hour("00"), Literal(":"), Minute("00"), Literal(" – "), Hour("00"), Literal(":"), Minute("02"), Literal(" "), TimeZoneName("UTC")], + shortOffset: [Hour("00"), Literal(":"), Minute("00"), Literal(" – "), Hour("00"), Literal(":"), Minute("02"), Literal(" "), TimeZoneName("GMT")], + shortGeneric: "shortOffset", + long: [Hour("00"), Literal(":"), Minute("00"), Literal(" – "), Hour("00"), Literal(":"), Minute("02"), Literal(" "), TimeZoneName("Coordinated Universal Time")], + longOffset: "shortOffset", + longGeneric: "shortOffset", + }, + }, + { + start: 0, + end: minutes(2), + timeZone: "America/New_York", + options: {hour: "numeric", minute: "numeric", hour12: false}, + timeZoneNames: { + short: [Hour("19"), Literal(":"), Minute("00"), Literal(" – "), Hour("19"), Literal(":"), Minute("02"), Literal(" "), TimeZoneName("EST")], + shortOffset: [Hour("19"), Literal(":"), Minute("00"), Literal(" – "), Hour("19"), Literal(":"), Minute("02"), Literal(" "), TimeZoneName("GMT-5")], + shortGeneric: [Hour("19"), Literal(":"), Minute("00"), Literal(" – "), Hour("19"), Literal(":"), Minute("02"), Literal(" "), TimeZoneName("ET")], + long: [Hour("19"), Literal(":"), Minute("00"), Literal(" – "), Hour("19"), Literal(":"), Minute("02"), Literal(" "), TimeZoneName("Eastern Standard Time")], + longOffset: [Hour("19"), Literal(":"), Minute("00"), Literal(" – "), Hour("19"), Literal(":"), Minute("02"), Literal(" "), TimeZoneName("GMT-05:00")], + longGeneric: [Hour("19"), Literal(":"), Minute("00"), Literal(" – "), Hour("19"), Literal(":"), Minute("02"), Literal(" "), TimeZoneName("Eastern Time")], + }, + }, + ], + "fr": [ + { + start: 0, + end: hours(2), + timeZone: "UTC", + options: {hour: "numeric", hour12: false}, + timeZoneNames: { + short: [Hour("00"), Literal(" – "), Hour("02"), Literal(" "), TimeZoneName("UTC")], + shortOffset: "short", + shortGeneric: "short", + long: [Hour("00"), Literal(" – "), Hour("02"), Literal(" "), TimeZoneName("temps universel coordonné")], + longOffset: "short", + longGeneric: "short", + }, + }, + { + start: minutes(15), + end: hours(5) + minutes(30), + timeZone: "Europe/Paris", + options: {hour: "numeric", minute: "numeric", hour12: false}, + timeZoneNames: { + short: [Hour("01"), Literal(":"), Minute("15"), Literal(" – "), Hour("06"), Literal(":"), Minute("30"), Literal(" "), TimeZoneName("UTC+1")], + shortOffset: "short", + shortGeneric: [Hour("01"), Literal(":"), Minute("15"), Literal(" – "), Hour("06"), Literal(":"), Minute("30"), Literal(" "), TimeZoneName("heure : France")], + long: [Hour("01"), Literal(":"), Minute("15"), Literal(" – "), Hour("06"), Literal(":"), Minute("30"), Literal(" "), TimeZoneName("heure normale d’Europe centrale")], + longOffset: [Hour("01"), Literal(":"), Minute("15"), Literal(" – "), Hour("06"), Literal(":"), Minute("30"), Literal(" "), TimeZoneName("UTC+01:00")], + longGeneric: "long", + }, + }, + ], + "de": [ + { + start: 0, + end: hours(2), + timeZone: "UTC", + options: {hour: "numeric", hour12: false}, + timeZoneNames: { + short: [Hour("00"), Literal("–"), Hour("02"), Literal(" Uhr "), TimeZoneName("UTC")], + shortOffset: [Hour("00"), Literal("–"), Hour("02"), Literal(" Uhr "), TimeZoneName("GMT")], + shortGeneric: "shortOffset", + long: [Hour("00"), Literal("–"), Hour("02"), Literal(" Uhr "), TimeZoneName("Koordinierte Weltzeit")], + longOffset: "shortOffset", + longGeneric: "shortOffset", + }, + }, + { + start: hours(5) + minutes(15), + end: hours(5) + minutes(30), + timeZone: "Europe/Berlin", + options: {hour: "numeric", minute: "numeric", hour12: false}, + timeZoneNames: { + short: [Hour("06"), Literal(":"), Minute("15"), Literal("–"), Hour("06"), Literal(":"), Minute("30"), Literal(" Uhr "), TimeZoneName("MEZ")], + shortOffset: [Hour("06"), Literal(":"), Minute("15"), Literal("–"), Hour("06"), Literal(":"), Minute("30"), Literal(" Uhr "), TimeZoneName("GMT+1")], + shortGeneric: "short", + long: [Hour("06"), Literal(":"), Minute("15"), Literal("–"), Hour("06"), Literal(":"), Minute("30"), Literal(" Uhr "), TimeZoneName("Mitteleuropäische Normalzeit")], + longOffset: [Hour("06"), Literal(":"), Minute("15"), Literal("–"), Hour("06"), Literal(":"), Minute("30"), Literal(" Uhr "), TimeZoneName("GMT+01:00")], + longGeneric: "long", + }, + }, + ], +}; + +for (let [locale, formats] of Object.entries(tests)) { + for (let {start, end, timeZone, options, timeZoneNames} of formats) { + for (let [timeZoneName, format] of Object.entries(timeZoneNames)) { + let df = new Intl.DateTimeFormat(locale, {timeZone, timeZoneName, ...options}); + if (typeof format === "string") { + format = timeZoneNames[format]; + } + assertRangeParts(df, start, end, format); + } + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/formatToParts.js b/js/src/tests/non262/Intl/DateTimeFormat/formatToParts.js new file mode 100644 index 0000000000..62f0d69406 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/formatToParts.js @@ -0,0 +1,96 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +// Tests the format function with a diverse set of locales and options. +// Always use UTC to avoid dependencies on test environment. + +const { + Era, Year, Month, Weekday, Day, DayPeriod, Hour, Minute, Second, Literal +} = DateTimeFormatParts + +var format; +var date = Date.UTC(2012, 11, 17, 3, 0, 42); + +// Locale en-US; default options. +format = new Intl.DateTimeFormat("en-us", {timeZone: "UTC"}); +assertParts(format, date, [ + Month("12"), Literal("/"), Day("17"), Literal("/"), Year("2012"), +]); + +// Just date +format = new Intl.DateTimeFormat("en-us", { + year: 'numeric', + month: 'numeric', + day: 'numeric', + timeZone: "UTC"}); +assertParts(format, date, [ + Month("12"), Literal("/"), Day("17"), Literal("/"), Year("2012"), +]); + +// Just time in hour24 +format = new Intl.DateTimeFormat("en-us", { + hour: 'numeric', + minute: 'numeric', + second: 'numeric', + hour12: false, + timeZone: "UTC"}); +assertParts(format, date, [ + Hour("03"), Literal(":"), Minute("00"), Literal(":"), Second("42"), +]); + +// Just time in hour12 +format = new Intl.DateTimeFormat("en-us", { + hour: 'numeric', + minute: 'numeric', + second: 'numeric', + hour12: true, + timeZone: "UTC"}); +assertParts(format, date, [ + Hour("3"), Literal(":"), Minute("00"), Literal(":"), Second("42"), Literal(" "), DayPeriod("AM"), +]); + +// Just month. +format = new Intl.DateTimeFormat("en-us", { + month: "narrow", + timeZone: "UTC"}); +assertParts(format, date, [ + Month("D"), +]); + +// Just weekday. +format = new Intl.DateTimeFormat("en-us", { + weekday: "narrow", + timeZone: "UTC"}); +assertParts(format, date, [ + Weekday("M"), +]); + +// Year and era. +format = new Intl.DateTimeFormat("en-us", { + year: "numeric", + era: "short", + timeZone: "UTC"}); +assertParts(format, date, [ + Year("2012"), Literal(" "), Era("AD"), +]); + +// Time and date +format = new Intl.DateTimeFormat("en-us", { + weekday: 'long', + year: 'numeric', + month: 'numeric', + day: 'numeric', + hour: 'numeric', + minute: 'numeric', + second: 'numeric', + hour12: true, + timeZone: "UTC"}); +assertParts(format, date, [ + Weekday("Monday"), Literal(", "), Month("12"), Literal("/"), Day("17"), Literal("/"), Year("2012"), + Literal(", "), + Hour("3"), Literal(":"), Minute("00"), Literal(":"), Second("42"), Literal(" "), DayPeriod("AM"), +]); + +if (typeof reportCompare === "function") + reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/format_timeZone-non-meta.js b/js/src/tests/non262/Intl/DateTimeFormat/format_timeZone-non-meta.js new file mode 100644 index 0000000000..f3de06bb97 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/format_timeZone-non-meta.js @@ -0,0 +1,62 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Ensure we provide 'long' and 'short' descriptive names for non-meta time +// zones. (CLDR stores names for Etc/UTC, Europe/Dublin, and Europe/London as +// non-meta zones.) + +const date = new Date(Date.UTC(2018, 7-1, 24)); +const tests = [ + { + locale: "en-US", + timeZoneName: "long", + zones: { + "Etc/UTC": "7/24/2018, Coordinated Universal Time", + "Europe/Dublin": "7/24/2018, Irish Standard Time", + "Europe/London": "7/24/2018, British Summer Time", + } + }, + { + locale: "de", + timeZoneName: "long", + zones: { + "Etc/UTC": "24.7.2018, Koordinierte Weltzeit", + "Europe/Dublin": "24.7.2018, Irische Sommerzeit", + "Europe/London": "24.7.2018, Britische Sommerzeit", + } + }, + + { + locale: "en-US", + timeZoneName: "short", + zones: { + "Europe/Dublin": "7/24/2018, GMT+1", + "Europe/London": "7/24/2018, GMT+1", + } + }, + { + locale: "en-GB", + timeZoneName: "short", + zones: { + "Europe/Dublin": "24/07/2018, GMT+1", + "Europe/London": "24/07/2018, BST", + } + }, + { + locale: "en-IE", + timeZoneName: "short", + zones: { + "Europe/Dublin": "24/7/2018, IST", + "Europe/London": "24/7/2018, GMT+1", + } + }, +]; + +for (let {locale, timeZoneName, zones} of tests) { + for (let [timeZone, expected] of Object.entries(zones)) { + assertEq(new Intl.DateTimeFormat(locale, {timeZone, timeZoneName}).format(date), + expected); + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/format_timeZone.js b/js/src/tests/non262/Intl/DateTimeFormat/format_timeZone.js new file mode 100644 index 0000000000..5cc3bf10cf --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/format_timeZone.js @@ -0,0 +1,104 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const defaultLocale = "en-US"; +const defaultDate = Date.UTC(2012, 12-1, 6, 12, 0, 0); +const defaultOptions = { + year: "numeric", month: "numeric", day: "numeric", + hour: "numeric", minute: "numeric", second: "numeric", +}; +const longFormatOptions = Object.assign({}, defaultOptions, { + month: "long" +}); +const tzNameFormatOptions = Object.assign({}, defaultOptions, { + timeZoneName: "short" +}); + +const tzMapper = [ + x => x, + x => x.toUpperCase(), + x => x.toLowerCase(), +]; + +const tests = [ + { + timeZone: "UTC", + result: "12/6/2012, 12:00:00 PM", + }, + { + timeZone: "America/Los_Angeles", + result: "12/6/2012, 4:00:00 AM", + }, + { + timeZone: "America/New_York", + options: tzNameFormatOptions, + result: "12/6/2012, 7:00:00 AM EST", + }, + { + timeZone: "America/Caracas", + result: "12/6/2012, 7:30:00 AM", + }, + { + timeZone: "Europe/London", + result: "12/6/2012, 12:00:00 PM", + }, + { + timeZone: "Africa/Casablanca", + locale: "ar-MA-u-ca-islamicc", options: longFormatOptions, + result: "22 محرم 1434 هـ في 12:00:00", + }, + { + timeZone: "Europe/Berlin", + locale: "de-DE", options: tzNameFormatOptions, + result: "6.12.2012, 13:00:00 MEZ", + }, + { + timeZone: "Asia/Kathmandu", + result: "12/6/2012, 5:45:00 PM", + }, + { + timeZone: "Asia/Bangkok", + locale: "th-th-u-nu-thai", options: longFormatOptions, + result: "๖ ธันวาคม ๒๕๕๕ เวลา ๑๙:๐๐:๐๐", + }, + { + timeZone: "Asia/Tokyo", + locale: "ja-JP", options: longFormatOptions, + result: "2012年12月6日 21:00:00", + }, + { + timeZone: "Australia/Lord_Howe", + result: "12/6/2012, 11:00:00 PM", + }, + { + timeZone: "Australia/Lord_Howe", + date: Date.UTC(2012, 7-1, 6, 12, 0, 0), + result: "7/6/2012, 10:30:00 PM", + }, + { + timeZone: "Pacific/Kiritimati", + date: Date.UTC(1978, 12-1, 6, 12, 0, 0), + result: "12/6/1978, 1:20:00 AM", + }, + { + timeZone: "Africa/Monrovia", + date: Date.UTC(1971, 12-1, 6, 12, 0, 0), + result: "12/6/1971, 11:15:30 AM", + }, + { + timeZone: "Asia/Riyadh", + date: Date.UTC(1946, 12-1, 6, 12, 0, 0), + result: "12/6/1946, 3:06:52 PM", + }, +]; + +for (let {timeZone, result, locale = defaultLocale, date = defaultDate, options = defaultOptions} of tests) { + for (let map of tzMapper) { + let dtf = new Intl.DateTimeFormat(locale, Object.assign({timeZone: map(timeZone)}, options)); + assertEq(dtf.format(date), result); + assertEq(dtf.resolvedOptions().timeZone, timeZone); + } +} + + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/fractional-second-digits-append-item.js b/js/src/tests/non262/Intl/DateTimeFormat/fractional-second-digits-append-item.js new file mode 100644 index 0000000000..0ef5540179 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/fractional-second-digits-append-item.js @@ -0,0 +1,58 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const { + DayPeriod, Hour, Minute, Second, FractionalSecond, Literal +} = DateTimeFormatParts + +const tests = [ + // https://unicode-org.atlassian.net/browse/CLDR-13184 + // https://unicode-org.atlassian.net/browse/CLDR-13623 + { + locale: "en", + date: new Date("2020-01-01T00:00:00.123"), + options: {hour: "numeric", fractionalSecondDigits: 3}, + parts: [ + Hour("12"), + Literal(" "), + DayPeriod("AM"), + Literal(" (Fractional Second: "), + FractionalSecond("123"), + Literal(")") + ] + }, + + // https://unicode-org.atlassian.net/browse/ICU-20992 + { + locale: "ckb-IR", + date: new Date("2020-01-01T00:00:00.123"), + options: {minute: "2-digit", fractionalSecondDigits: 3}, + parts: [ + Minute("٠٠"), + Literal(":"), + Second("٠٠"), + Literal("٫"), + FractionalSecond("١٢٣"), + ] + }, + + // https://unicode-org.atlassian.net/browse/ICU-20992 + { + locale: "ckb-IR", + date: new Date("2020-01-01T00:00:00.123"), + options: {dayPeriod: "short", fractionalSecondDigits: 3}, + parts: [ + FractionalSecond("١٢٣"), + Literal(" (Dayperiod: "), + DayPeriod("ب.ن"), + Literal(")") + ] + }, +]; + +for (let {locale, date, options, parts} of tests) { + let dtf = new Intl.DateTimeFormat(locale, options); + assertParts(dtf, date, parts); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/fractional-second-digits.js b/js/src/tests/non262/Intl/DateTimeFormat/fractional-second-digits.js new file mode 100644 index 0000000000..c6c29be604 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/fractional-second-digits.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const { + Second, FractionalSecond, Literal +} = DateTimeFormatParts + +const tests = [ + { + date: new Date("2019-01-01T00:00:00.123"), + digits: { + 1: [Second("0"), Literal("."), FractionalSecond("1")], + 2: [Second("0"), Literal("."), FractionalSecond("12")], + 3: [Second("0"), Literal("."), FractionalSecond("123")], + } + }, + { + date: new Date("2019-01-01T00:00:00.023"), + digits: { + 1: [Second("0"), Literal("."), FractionalSecond("0")], + 2: [Second("0"), Literal("."), FractionalSecond("02")], + 3: [Second("0"), Literal("."), FractionalSecond("023")], + } + }, + { + date: new Date("2019-01-01T00:00:00.003"), + digits: { + 1: [Second("0"), Literal("."), FractionalSecond("0")], + 2: [Second("0"), Literal("."), FractionalSecond("00")], + 3: [Second("0"), Literal("."), FractionalSecond("003")], + } + }, +]; + +for (let {date, digits} of tests) { + for (let [fractionalSecondDigits, parts] of Object.entries(digits)) { + let dtf = new Intl.DateTimeFormat("en", {second: "numeric", fractionalSecondDigits}); + + assertParts(dtf, date, parts); + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/hourCycle.js b/js/src/tests/non262/Intl/DateTimeFormat/hourCycle.js new file mode 100644 index 0000000000..21414c72cf --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/hourCycle.js @@ -0,0 +1,142 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const hourCycleToH12Map = { + "h11": true, + "h12": true, + "h23": false, + "h24": false, +}; + +for (const key of Object.keys(hourCycleToH12Map)) { + const langTag = "en-US"; + const loc = `${langTag}-u-hc-${key}`; + + const dtf = new Intl.DateTimeFormat(loc, {hour: "numeric"}); + const dtf2 = new Intl.DateTimeFormat(langTag, {hour: "numeric", hourCycle: key}); + assertEq(dtf.resolvedOptions().hourCycle, dtf2.resolvedOptions().hourCycle); +} + + +/* Legacy hour12 compatibility */ + +// When constructed with hourCycle option, resolvedOptions' hour12 is correct. +for (const key of Object.keys(hourCycleToH12Map)) { + const dtf = new Intl.DateTimeFormat("en-US", {hour: "numeric", hourCycle: key}); + assertEq(dtf.resolvedOptions().hour12, hourCycleToH12Map[key]); +} + +// When constructed with hour12 option, resolvedOptions' hourCycle is correct +for (const [key, value] of Object.entries(hourCycleToH12Map)) { + const dtf = new Intl.DateTimeFormat("en-US", {hour: "numeric", hour12: value}); + assertEq(hourCycleToH12Map[dtf.resolvedOptions().hourCycle], value); +} + +// When constructed with both hour12 and hourCycle options that don't match +// hour12 takes a precedence. +for (const [key, value] of Object.entries(hourCycleToH12Map)) { + const dtf = new Intl.DateTimeFormat("en-US", { + hour: "numeric", + hourCycle: key, + hour12: !value + }); + assertEq(hourCycleToH12Map[dtf.resolvedOptions().hourCycle], !value); + assertEq(dtf.resolvedOptions().hour12, !value); +} + +// When constructed with hourCycle as extkey, resolvedOptions' hour12 is correct. +for (const [key, value] of Object.entries(hourCycleToH12Map)) { + const langTag = "en-US"; + const loc = `${langTag}-u-hc-${key}`; + + const dtf = new Intl.DateTimeFormat(loc, {hour: "numeric"}); + assertEq(dtf.resolvedOptions().hour12, value); +} + +const expectedValuesENUS = { + h11: "0 AM", + h12: "12 AM", + h23: "00", + h24: "24" +}; + +const exampleDate = new Date(2017, 10-1, 10, 0); +for (const [key, val] of Object.entries(expectedValuesENUS)) { + assertEq( + Intl.DateTimeFormat("en-US", {hour: "numeric", hourCycle: key}).format(exampleDate), + val + ); +} + +const invalidHourCycleValues = [ + "h28", + "f28", +]; + +for (const key of invalidHourCycleValues) { + const langTag = "en-US"; + const loc = `${langTag}-u-hc-${key}`; + + const dtf = new Intl.DateTimeFormat(loc, {hour: "numeric"}); + assertEq(dtf.resolvedOptions().hour12, true); // default value for en-US + assertEq(dtf.resolvedOptions().hourCycle, "h12"); //default value for en-US +} + +{ + // hourCycle is not present in resolvedOptions when the formatter has no hour field + const options = Intl.DateTimeFormat("en-US", {hourCycle:"h11"}).resolvedOptions(); + assertEq("hourCycle" in options, false); + assertEq("hour12" in options, false); +} + +{ + // Make sure that hourCycle option overrides the unicode extension + let dtf = Intl.DateTimeFormat("en-US-u-hc-h23", {hourCycle: "h24", hour: "numeric"}); + assertEq( + dtf.resolvedOptions().hourCycle, + "h24" + ); +} + +{ + // Make sure that hour12 option overrides the unicode extension + let dtf = Intl.DateTimeFormat("en-US-u-hc-h23", {hour12: true, hour: "numeric"}); + assertEq( + dtf.resolvedOptions().hourCycle, + "h12" + ); +} + +{ + // Make sure that hour12 option overrides hourCycle options + let dtf = Intl.DateTimeFormat("en-US", + {hourCycle: "h12", hour12: false, hour: "numeric"}); + assertEq( + dtf.resolvedOptions().hourCycle, + "h23" + ); +} + +{ + // Make sure that hour12 option overrides hourCycle options + let dtf = Intl.DateTimeFormat("en-u-hc-h11", {hour: "numeric"}); + assertEq( + dtf.resolvedOptions().locale, + "en-u-hc-h11" + ); +} + +{ + // Make sure that hour12 option overrides unicode extension + let dtf = Intl.DateTimeFormat("en-u-hc-h11", {hour: "numeric", hourCycle: "h24"}); + assertEq( + dtf.resolvedOptions().locale, + "en" + ); + assertEq( + dtf.resolvedOptions().hourCycle, + "h24" + ); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/implied-script-has-consistent-output.js b/js/src/tests/non262/Intl/DateTimeFormat/implied-script-has-consistent-output.js new file mode 100644 index 0000000000..6c0b4d2f59 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/implied-script-has-consistent-output.js @@ -0,0 +1,59 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +if (typeof getAvailableLocalesOf === "undefined") { + var getAvailableLocalesOf = SpecialPowers.Cu.getJSTestingFunctions().getAvailableLocalesOf; +} + +// Retrieve all available locales of Intl.DateTimeFormat. +const available = getAvailableLocalesOf("DateTimeFormat"); + +const options = [ + // Include "hour" to catch hour cycle differences. + // + // For example "ff-Latn-GH" (Fulah as spoken in Ghana) uses a 12-hour clock, + // whereas "ff" (Fulah) uses a 24-hour clock. When the user creates the + // formatter for "ff-GH", it should use the same formatter data as "ff-Latn-GH" + // and it shouldn't fallback to "ff". + {hour: "2-digit", minute: "2-digit", timeZone: "UTC"}, + + // Include "timeZoneName" to catch script differences, e.g traditional or + // simplified Chinese characters. + {timeZoneName: "long", timeZone: "America/Los_Angeles"}, +]; + +// Pick a date after 12 pm to catch any hour cycle differences. +const date = Date.UTC(2021, 6-1, 7, 15, 0); + +available.map(x => { + return new Intl.Locale(x); +}).filter(loc => { + // Find all locales which have both a script and a region subtag. + return loc.script && loc.region; +}).filter(loc => { + // Skip "sd-Deva-IN" and Fulah because of . + return !((loc.language === "sd" && loc.script === "Deva" && loc.region === "IN") || + (loc.language === "ff" && (loc.script === "Adlm" || loc.script === "Latn") && + (loc.region === "GH" || loc.region === "GM" || loc.region === "LR" || loc.region === "SL")) + ); +}).forEach(loc => { + // Remove the script subtag from the locale. + let noScript = new Intl.Locale(`${loc.language}-${loc.region}`); + + // Add the likely script subtag. + let maximized = noScript.maximize(); + + for (let opt of options) { + // Formatter for the locale without a script subtag. + let df1 = new Intl.DateTimeFormat(noScript, opt); + + // Formatter for the locale with the likely script subtag added. + let df2 = new Intl.DateTimeFormat(maximized, opt); + + // The output for the locale without a script subtag should match the output + // with the likely script subtag added. + assertEq(df1.format(date), df2.format(date), `Mismatch for locale "${noScript}" (${maximized})`); + } +}); + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/islamic.js b/js/src/tests/non262/Intl/DateTimeFormat/islamic.js new file mode 100644 index 0000000000..3a88590ea5 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/islamic.js @@ -0,0 +1,89 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +function civilDate(options, date) { + var opts = Object.assign({timeZone: "Asia/Riyadh"}, options); + return new Intl.DateTimeFormat("ar-SA-u-ca-islamic-civil-nu-latn", opts).format(date); +} + +function tabularDate(options, date) { + var opts = Object.assign({timeZone: "Asia/Riyadh"}, options); + return new Intl.DateTimeFormat("ar-SA-u-ca-islamic-tbla-nu-latn", opts).format(date); +} + +function sightingDate(options, date) { + var opts = Object.assign({timeZone: "Asia/Riyadh"}, options); + return new Intl.DateTimeFormat("ar-SA-u-ca-islamic-rgsa-nu-latn", opts).format(date); +} + +function ummAlQuraDate(options, date) { + var opts = Object.assign({timeZone: "Asia/Riyadh"}, options); + return new Intl.DateTimeFormat("ar-SA-u-ca-umalqura-nu-latn", opts).format(date); +} + +// Test islamic-tbla (Tabular / Thursday epoch). +// Compare with islamic-civil (Tabular / Friday epoch). +function testIslamicTbla() { + var date = new Date(Date.UTC(2015, 1 - 1, 1)); + + // Month and year are the same. + var monthYear = {year: "numeric", month: "numeric"}; + assertEq(civilDate(monthYear, date), tabularDate(monthYear, date)); + + // Day is different by one. + var day = {day: "numeric"}; + assertEq(Number(civilDate(day, date)) - Number(tabularDate(day, date)), -1); +} + +// Test islamic-rgsa (Saudi Arabia sighting). +// Sighting of the hilal (crescent moon) in Saudi Arabia. +function testIslamicRgsa() { + var date1 = new Date(Date.UTC(1975, 5 - 1, 6)); + var date2 = new Date(Date.UTC(2015, 1 - 1, 1)); + var dayMonthYear = {year: "numeric", month: "numeric", day: "numeric"}; + + assertEq(sightingDate(dayMonthYear, date1), tabularDate(dayMonthYear, date1)); + assertEq(sightingDate(dayMonthYear, date2), civilDate(dayMonthYear, date2)); +} + +// Test islamic-umalqura (Umm al-Qura). +function testIslamicUmalqura() { + var year = {year: "numeric"}; + var month = {month: "numeric"}; + var day = {day: "numeric"}; + + // From ICU test files, which in turn was generated from: + // Official Umm-al-Qura calendar of SA: + // home, http://www.ummulqura.org.sa/default.aspx + // converter, http://www.ummulqura.org.sa/Index.aspx + var dates = [ + [ {year: 2016, month: 1, day: 11}, {year: 1437, month: 4, day: 1} ], + [ {year: 2016, month: 2, day: 10}, {year: 1437, month: 5, day: 1} ], + [ {year: 2016, month: 3, day: 10}, {year: 1437, month: 6, day: 1} ], + [ {year: 2016, month: 4, day: 8}, {year: 1437, month: 7, day: 1} ], + [ {year: 2016, month: 5, day: 8}, {year: 1437, month: 8, day: 1} ], + [ {year: 2016, month: 6, day: 6}, {year: 1437, month: 9, day: 1} ], + [ {year: 2016, month: 7, day: 6}, {year: 1437, month: 10, day: 1} ], + [ {year: 2016, month: 8, day: 4}, {year: 1437, month: 11, day: 1} ], + [ {year: 2016, month: 9, day: 2}, {year: 1437, month: 12, day: 1} ], + [ {year: 2016, month: 10, day: 2}, {year: 1438, month: 1, day: 1} ], + [ {year: 2016, month: 11, day: 1}, {year: 1438, month: 2, day: 1} ], + [ {year: 2016, month: 11, day: 30}, {year: 1438, month: 3, day: 1} ], + [ {year: 2016, month: 12, day: 30}, {year: 1438, month: 4, day: 1} ], + ]; + + for (var [gregorian, ummAlQura] of dates) { + var date = new Date(Date.UTC(gregorian.year, gregorian.month - 1, gregorian.day)); + + // Use parseInt() to remove the trailing era indicator. + assertEq(parseInt(ummAlQuraDate(year, date), 10), ummAlQura.year); + assertEq(Number(ummAlQuraDate(month, date)), ummAlQura.month); + assertEq(Number(ummAlQuraDate(day, date)), ummAlQura.day); + } +} + +testIslamicTbla(); +testIslamicRgsa(); +testIslamicUmalqura(); + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/japanese-gannen-year.js b/js/src/tests/non262/Intl/DateTimeFormat/japanese-gannen-year.js new file mode 100644 index 0000000000..e972d2e55a --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/japanese-gannen-year.js @@ -0,0 +1,54 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +var dtf = new Intl.DateTimeFormat("ja-u-ca-japanese", { + era: "short", + timeZone: "Asia/Tokyo", +}); + +var endShowa = new Date("1989-01-07T00:00:00.000Z"); +var startHeisei = new Date("1989-01-08T00:00:00.000Z"); + +assertEq(dtf.format(endShowa), "昭和64/1/7"); +assertEq(dtf.format(startHeisei), "平成1/1/8"); + +var parts = dtf.formatToParts(startHeisei); +assertEq(parts.filter(p => p.type === "era")[0].value, "平成"); +assertEq(parts.filter(p => p.type === "year")[0].value, "1"); + +var dtf = new Intl.DateTimeFormat("ja-u-ca-japanese", { + era: "short", + year: "numeric", + month: "long", + day: "numeric", + timeZone: "Asia/Tokyo", +}); + +assertEq(dtf.format(endShowa), "昭和64年1月7日"); +assertEq(dtf.format(startHeisei), "平成元年1月8日"); + +var parts = dtf.formatToParts(startHeisei); +assertEq(parts.filter(p => p.type === "era")[0].value, "平成"); +assertEq(parts.filter(p => p.type === "year")[0].value, "元"); + +// ICU returns mixed numbers when an explicit numbering system is present. + +var dtf = new Intl.DateTimeFormat("ja-u-ca-japanese-nu-arab", { + era: "short", + timeZone: "Asia/Tokyo", +}); + +assertEq(dtf.format(endShowa), "昭和٦٤/١/٧"); +assertEq(dtf.format(startHeisei), "平成١/١/٨"); + +var dtf = new Intl.DateTimeFormat("ja-u-ca-japanese-nu-arab", { + era: "short", + year: "numeric", + month: "numeric", + timeZone: "Asia/Tokyo", +}); + +assertEq(dtf.format(endShowa), "昭和64年١月"); +assertEq(dtf.format(startHeisei), "平成元年١月"); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/mozExtensions.js b/js/src/tests/non262/Intl/DateTimeFormat/mozExtensions.js new file mode 100644 index 0000000000..7db314d413 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/mozExtensions.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")||!this.hasOwnProperty("addIntlExtras")) +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +let mozIntl = {}; +addIntlExtras(mozIntl); + +// Pattern + +var dtf = new Intl.DateTimeFormat("en-US", {pattern: "HH:mm MM/dd/YYYY"}); +var mozDtf = new mozIntl.DateTimeFormat("en-US", {pattern: "HH:mm MM/dd/YYYY"}); + +assertEq(dtf.resolvedOptions().hasOwnProperty('pattern'), false); +assertEq(mozDtf.resolvedOptions().pattern, "HH:mm MM/dd/YYYY"); + +if (typeof reportCompare === "function") + reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/numberingSystem-option.js b/js/src/tests/non262/Intl/DateTimeFormat/numberingSystem-option.js new file mode 100644 index 0000000000..474910da47 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/numberingSystem-option.js @@ -0,0 +1,60 @@ +const defaultLocale = "en"; +const defaultNumberingSystem = new Intl.DateTimeFormat(defaultLocale).resolvedOptions().numberingSystem; + +function createWithLocale(locale, numberingSystem) { + return new Intl.DateTimeFormat(locale, {numberingSystem}); +} + +function create(numberingSystem) { + return createWithLocale(defaultLocale, numberingSystem); +} + +// Empty string should throw. +assertThrowsInstanceOf(() => create(""), RangeError); + +// Trailing \0 should throw. +assertThrowsInstanceOf(() => create("latn\0"), RangeError); + +// Too short or too long strings should throw. +assertThrowsInstanceOf(() => create("a"), RangeError); +assertThrowsInstanceOf(() => create("toolongstring"), RangeError); + +// Throw even when prefix is valid. +assertThrowsInstanceOf(() => create("latn-toolongstring"), RangeError); + +// |numberingSystem| can be set to |undefined|. +let dtf = create(undefined); +assertEq(dtf.resolvedOptions().numberingSystem, defaultNumberingSystem); + +// Unsupported numbering systems are ignored. +dtf = create("xxxxxxxx"); +assertEq(dtf.resolvedOptions().numberingSystem, defaultNumberingSystem); + +// Numbering system in options overwrite Unicode extension keyword. +dtf = createWithLocale(`${defaultLocale}-u-nu-thai`, "arab"); +assertEq(dtf.resolvedOptions().locale, defaultLocale); +assertEq(dtf.resolvedOptions().numberingSystem, "arab"); + +// |numberingSystem| option ignores case. +dtf = create("ARAB"); +assertEq(dtf.resolvedOptions().locale, defaultLocale); +assertEq(dtf.resolvedOptions().numberingSystem, "arab"); + +for (let [numberingSystem, {algorithmic}] of Object.entries(numberingSystems)) { + let dtf1 = new Intl.DateTimeFormat(`${defaultLocale}-u-nu-${numberingSystem}`); + let dtf2 = new Intl.DateTimeFormat(defaultLocale, {numberingSystem}); + + if (!algorithmic) { + assertEq(dtf1.resolvedOptions().numberingSystem, numberingSystem); + assertEq(dtf2.resolvedOptions().numberingSystem, numberingSystem); + } else { + // We don't yet support algorithmic numbering systems. + assertEq(dtf1.resolvedOptions().numberingSystem, defaultNumberingSystem); + assertEq(dtf2.resolvedOptions().numberingSystem, defaultNumberingSystem); + } + + assertEq(dtf2.format(0), dtf1.format(0)); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/options-property-accesses.js b/js/src/tests/non262/Intl/DateTimeFormat/options-property-accesses.js new file mode 100644 index 0000000000..66ecf9ef32 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/options-property-accesses.js @@ -0,0 +1,53 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +var log; +var proxy = new Proxy({ + year: "numeric", + hour: "numeric", +}, new Proxy({ + get(t, pk, r) { + log.push(pk); + return Reflect.get(t, pk, r); + } +}, { + get(t, pk, r) { + assertEq(pk, "get"); + return Reflect.get(t, pk, r); + } +})); + +var constructorAccesses = [ + // InitializeDateTimeFormat + "localeMatcher", "calendar", "numberingSystem", "hour12", "hourCycle", "timeZone", + + // Table 5: Components of date and time formats + "weekday", "era", "year", "month", "day", "dayPeriod", "hour", "minute", "second", + "fractionalSecondDigits", "timeZoneName", + + // InitializeDateTimeFormat + "formatMatcher", + "dateStyle", "timeStyle", +]; + +log = []; +new Intl.DateTimeFormat(undefined, proxy); + +assertEqArray(log, constructorAccesses); + +log = []; +new Date().toLocaleString(undefined, proxy); + +assertEqArray(log, constructorAccesses); + +log = []; +new Date().toLocaleDateString(undefined, proxy); + +assertEqArray(log, constructorAccesses); + +log = []; +new Date().toLocaleTimeString(undefined, proxy); + +assertEqArray(log, constructorAccesses); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/related-year.js b/js/src/tests/non262/Intl/DateTimeFormat/related-year.js new file mode 100644 index 0000000000..296de04883 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/related-year.js @@ -0,0 +1,185 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const { + Era, Year, YearName, RelatedYear, Month, Day, Literal +} = DateTimeFormatParts + +const tests = [ + // Test with non-leap month. + { + date: new Date("2020-04-23T00:00:00Z"), + options: {}, + calendar: "chinese", + locales: { + "en": [Month("4"), Literal("/"), Day("1"), Literal("/"), RelatedYear("2020")], + "de": [Day("1"), Literal("."), Month("4"), Literal("."), Year("37")], + "ja": [YearName("庚子"), Literal("-"), Month("4"), Literal("-"), Day("1")], + "zh": [RelatedYear("2020"), Literal("年"), Month("四月"), Day("1")], + "ar": [RelatedYear("٢٠٢٠"), Literal("-"), Month("٠٤"), Literal("-"), Day("٠١")], + } + }, + + // Test with leap month. + { + date: new Date("2020-05-23T00:00:00Z"), + options: {}, + calendar: "chinese", + locales: { + "en": [Month("4bis"), Literal("/"), Day("1"), Literal("/"), RelatedYear("2020")], + "de": [Day("1"), Literal("."), Month("4bis"), Literal("."), Year("37")], + "ja": [YearName("庚子"), Literal("-"), Month("閏4"), Literal("-"), Day("1")], + "zh": [RelatedYear("2020"), Literal("年"), Month("闰四月"), Day("1")], + "ar": [RelatedYear("٢٠٢٠"), Literal("-"), Month("٠٤bis"), Literal("-"), Day("٠١")], + } + }, + + // Display only "year" field. + { + date: new Date("2020-04-23T00:00:00Z"), + options: {year: "numeric"}, + calendar: "chinese", + locales: { + "en": [RelatedYear("2020"), Literal("("), YearName("geng-zi"), Literal(")")], + "de": [YearName("geng-zi")], + "ja": [YearName("庚子"), Literal("年")], + "zh": [RelatedYear("2020"), YearName("庚子"), Literal("年")], + "ar": [Year("٣٧")], + } + }, + + // Display only "month" field. + { + date: new Date("2020-04-23T00:00:00Z"), + options: {month: "long"}, + calendar: "chinese", + locales: { + "en": [Month("Fourth Month")], + "de": [Month("M04")], + "ja": [Month("四月")], + "zh": [Month("四月")], + "ar": [Month("M04")], + } + }, + + // Display only "month" field. (Leap month) + { + date: new Date("2020-05-23T00:00:00Z"), + options: {month: "long"}, + calendar: "chinese", + locales: { + "en": [Month("Fourth Monthbis")], + "de": [Month("M04bis")], + "ja": [Month("閏四月")], + "zh": [Month("闰四月")], + "ar": [Month("M04bis")], + } + }, + + // Display "year" and "month" fields. + { + date: new Date("2020-04-23T00:00:00Z"), + options: {year: "numeric", month: "long"}, + calendar: "chinese", + locales: { + "en": [Month("Fourth Month"), Literal(" "), RelatedYear("2020"), Literal("("), YearName("geng-zi"), Literal(")")], + "de": [Month("M04"), Literal(" "), YearName("geng-zi")], + "ja": [YearName("庚子"), Literal("年"), Month("四月")], + "zh": [RelatedYear("2020"), YearName("庚子"), Literal("年"), Month("四月")], + "ar": [RelatedYear("٢٠٢٠"), Literal("("), YearName("geng-zi"), Literal(") "), Month("M04")], + } + }, + + // Display "year" and "month" fields. (Leap month) + { + date: new Date("2020-05-23T00:00:00Z"), + options: {year: "numeric", month: "long"}, + calendar: "chinese", + locales: { + "en": [Month("Fourth Monthbis"), Literal(" "), RelatedYear("2020"), Literal("("), YearName("geng-zi"), Literal(")")], + "de": [Month("M04bis"), Literal(" "), YearName("geng-zi")], + "ja": [YearName("庚子"), Literal("年"), Month("閏四月")], + "zh": [RelatedYear("2020"), YearName("庚子"), Literal("年"), Month("闰四月")], + "ar": [RelatedYear("٢٠٢٠"), Literal("("), YearName("geng-zi"), Literal(") "), Month("M04bis")], + } + }, + + // Related year in traditional Korean calendar. + { + date: new Date("2019-01-01T00:00:00Z"), + options: {}, + calendar: "dangi", + locales: { + "en": [Month("11"), Literal("/"), Day("26"), Literal("/"), RelatedYear("2018")], + "ko": [RelatedYear("2018"), Literal(". "), Month("11"), Literal(". "), Day("26"), Literal(".")], + } + }, + + // Allowing the calendar to modify the pattern selection choice can result in falling back to + // the root locale patterns in more cases. That can result in displaying the era field by + // default, among other things. + { + date: new Date("2019-01-01T00:00:00Z"), + options: {}, + calendar: "buddhist", + locales: { + "en": [Month("1"), Literal("/"), Day("1"), Literal("/"), Year("2562"), Literal(" "), Era("BE")], + "th": [Day("1"), Literal("/"), Month("1"), Literal("/"), Year("2562")], + } + }, + { + date: new Date("2019-01-01T00:00:00Z"), + options: {}, + calendar: "hebrew", + locales: { + "en": [Day("24"), Literal(" "), Month("Tevet"), Literal(" "), Year("5779")], + "he": [Day("24"), Literal(" ב"), Month("טבת"), Literal(" "), Year("5779")], + "fr": [Day("24"), Literal("/"), Month("04"), Literal("/"), Year("5779"), Literal(" "), Era("A. M.")], + } + }, + { + date: new Date("2019-01-01T00:00:00Z"), + options: {}, + calendar: "islamic", + locales: { + "en": [Month("4"), Literal("/"), Day("25"), Literal("/"), Year("1440"), Literal(" "), Era("AH")], + "ar": [Day("٢٥"), Literal("\u200F/"), Month("٤"), Literal("\u200F/"), Year("١٤٤٠"), Literal(" "), Era("هـ")], + } + }, + { + date: new Date("2019-01-01T00:00:00Z"), + options: {}, + calendar: "japanese", + locales: { + "en": [Month("1"), Literal("/"), Day("1"), Literal("/"), Year("31"), Literal(" "), Era("H")], + "ja": [Era("H"), Year("31"), Literal("/"), Month("1"), Literal("/"), Day("1")], + } + }, + { + date: new Date("2019-01-01T00:00:00Z"), + options: {}, + calendar: "persian", + locales: { + "en": [Month("10"), Literal("/"), Day("11"), Literal("/"), Year("1397"), Literal(" "), Era("AP")], + "fa": [Year("۱۳۹۷"), Literal("/"), Month("۱۰"), Literal("/"), Day("۱۱")], + } + }, + { + date: new Date("2019-01-01T00:00:00Z"), + options: {}, + calendar: "roc", + locales: { + "en": [Month("1"), Literal("/"), Day("1"), Literal("/"), Year("108"), Literal(" "), Era("Minguo")], + "zh-Hant-TW": [Era("民國"), Year("108"), Literal("/"), Month("1"), Literal("/"), Day("1")], + } + }, +]; + +for (let {date, options, calendar, locales} of tests) { + for (let [locale, result] of Object.entries(locales)) { + let df = new Intl.DateTimeFormat(`${locale}-u-ca-${calendar}`, {timeZone: "UTC", ...options}); + assertParts(df, date, result); + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/shell.js b/js/src/tests/non262/Intl/DateTimeFormat/shell.js new file mode 100644 index 0000000000..a785a2cd01 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/shell.js @@ -0,0 +1,136 @@ +function GenericPartCreator(type) { + return str => ({ type, value: str }); +} + +const DateTimeFormatParts = { + Weekday: GenericPartCreator("weekday"), + Era: GenericPartCreator("era"), + Year: GenericPartCreator("year"), + YearName: GenericPartCreator("yearName"), + RelatedYear: GenericPartCreator("relatedYear"), + Month: GenericPartCreator("month"), + Day: GenericPartCreator("day"), + DayPeriod: GenericPartCreator("dayPeriod"), + Hour: GenericPartCreator("hour"), + Minute: GenericPartCreator("minute"), + Second: GenericPartCreator("second"), + FractionalSecond: GenericPartCreator("fractionalSecond"), + TimeZoneName: GenericPartCreator("timeZoneName"), + Unknown: GenericPartCreator("unknown"), + Literal: GenericPartCreator("literal"), +}; + +function assertParts(df, x, expected) { + var parts = df.formatToParts(x); + assertEq(parts.map(part => part.value).join(""), df.format(x), + "formatToParts and format must agree"); + + var len = parts.length; + assertEq(len, expected.length, "parts count mismatch"); + for (var i = 0; i < len; i++) { + assertEq(parts[i].type, expected[i].type, "type mismatch at " + i); + assertEq(parts[i].value, expected[i].value, "value mismatch at " + i); + } + + // Formatted parts must be consistent with the resolved options. + var resolvedOptions = df.resolvedOptions(); + + assertEq("dateStyle" in resolvedOptions, false, "dateStyle isn't yet supported here"); + assertEq("timeStyle" in resolvedOptions, false, "timeStyle isn't yet supported here"); + + // Every formatted part must be in the resolved options. + for (var {type} of expected) { + switch (type) { + case "weekday": + case "era": + case "month": + case "day": + case "hour": + case "minute": + case "second": + case "timeZoneName": + assertEq(type in resolvedOptions, true, JSON.stringify(resolvedOptions)); + break; + + case "year": + case "yearName": + case "relatedYear": + assertEq("year" in resolvedOptions, true); + break; + + case "dayPeriod": + assertEq("dayPeriod" in resolvedOptions || resolvedOptions.hour12 === true, true); + break; + + case "fractionalSecond": + assertEq("fractionalSecondDigits" in resolvedOptions, true); + break; + + case "unknown": + case "literal": + break; + + default: + assertEq(true, false, `invalid part: ${type}`); + } + } + + function includesType(...types) { + return parts.some(({type}) => types.includes(type)); + } + + // Every resolved option must be in the formatted parts. + for (var key of Object.keys(resolvedOptions)) { + switch (key) { + case "locale": + case "calendar": + case "numberingSystem": + case "timeZone": + case "hourCycle": + // Skip over non-pattern keys. + break; + + case "hour12": + if (resolvedOptions.hour12) { + assertEq(includesType("dayPeriod"), true); + } + break; + + case "weekday": + case "era": + case "month": + case "day": + case "dayPeriod": + case "hour": + case "minute": + case "second": + case "timeZoneName": + assertEq(includesType(key), true); + break; + + case "year": + assertEq(includesType("year", "yearName", "relatedYear"), true); + break; + + case "fractionalSecondDigits": + assertEq(includesType("fractionalSecond"), true); + break; + + default: + assertEq(true, false, `invalid key: ${key}`); + } + } +} + +function assertRangeParts(df, start, end, expected) { + var parts = df.formatRangeToParts(start, end); + assertEq(parts.map(part => part.value).join(""), df.formatRange(start, end), + "formatRangeToParts and formatRange must agree"); + + var len = parts.length; + assertEq(len, expected.length, "parts count mismatch"); + for (var i = 0; i < len; i++) { + assertEq(parts[i].type, expected[i].type, "type mismatch at " + i); + assertEq(parts[i].value, expected[i].value, "value mismatch at " + i); + } +} diff --git a/js/src/tests/non262/Intl/DateTimeFormat/standalone-month.js b/js/src/tests/non262/Intl/DateTimeFormat/standalone-month.js new file mode 100644 index 0000000000..c8aab5888e --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/standalone-month.js @@ -0,0 +1,11 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +for (let weekday of ["long", "short", "narrow"]) { + let dtf = new Intl.DateTimeFormat("en", {weekday}); + let options = dtf.resolvedOptions(); + + assertEq(options.weekday, weekday); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/supportedLocalesOf.js b/js/src/tests/non262/Intl/DateTimeFormat/supportedLocalesOf.js new file mode 100644 index 0000000000..b957f9cd60 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/supportedLocalesOf.js @@ -0,0 +1,371 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")||xulRuntime.shell) +// -- test in browser only that ICU has locale data for all Mozilla languages + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// This array contains the locales that ICU supports in +// date and time formatting whose languages Mozilla localizes Firefox into. +// Current as of ICU 50.1.2 and Firefox March 2013. +var locales = [ + "af", + "af-NA", + "af-ZA", + "ar", + "ar-001", + "ar-AE", + "ar-BH", + "ar-DJ", + "ar-DZ", + "ar-EG", + "ar-EH", + "ar-ER", + "ar-IL", + "ar-IQ", + "ar-JO", + "ar-KM", + "ar-KW", + "ar-LB", + "ar-LY", + "ar-MA", + "ar-MR", + "ar-OM", + "ar-PS", + "ar-QA", + "ar-SA", + "ar-SD", + "ar-SO", + "ar-SY", + "ar-TD", + "ar-TN", + "ar-YE", + "as", + "as-IN", + "be", + "be-BY", + "bg", + "bg-BG", + "bn", + "bn-BD", + "bn-IN", + "br", + "br-FR", + "bs", + "bs-Cyrl", + "bs-Cyrl-BA", + "bs-Latn", + "bs-Latn-BA", + "ca", + "ca-AD", + "ca-ES", + "cs", + "cs-CZ", + "cy", + "cy-GB", + "da", + "da-DK", + "de", + "de-AT", + "de-BE", + "de-CH", + "de-DE", + "de-LI", + "de-LU", + "el", + "el-CY", + "el-GR", + "en", + "en-150", + "en-AG", + "en-AS", + "en-AU", + "en-BB", + "en-BE", + "en-BM", + "en-BS", + "en-BW", + "en-BZ", + "en-CA", + "en-CM", + "en-DM", + "en-FJ", + "en-FM", + "en-GB", + "en-GD", + "en-GG", + "en-GH", + "en-GI", + "en-GM", + "en-GU", + "en-GY", + "en-HK", + "en-IE", + "en-IM", + "en-IN", + "en-JE", + "en-JM", + "en-KE", + "en-KI", + "en-KN", + "en-KY", + "en-LC", + "en-LR", + "en-LS", + "en-MG", + "en-MH", + "en-MP", + "en-MT", + "en-MU", + "en-MW", + "en-NA", + "en-NG", + "en-NZ", + "en-PG", + "en-PH", + "en-PK", + "en-PR", + "en-PW", + "en-SB", + "en-SC", + "en-SG", + "en-SL", + "en-SS", + "en-SZ", + "en-TC", + "en-TO", + "en-TT", + "en-TZ", + "en-UG", + "en-UM", + "en-US", + "en-US-POSIX", + "en-VC", + "en-VG", + "en-VI", + "en-VU", + "en-WS", + "en-ZA", + "en-ZM", + "en-ZW", + "eo", + "es", + "es-419", + "es-AR", + "es-BO", + "es-CL", + "es-CO", + "es-CR", + "es-CU", + "es-DO", + "es-EA", + "es-EC", + "es-ES", + "es-GQ", + "es-GT", + "es-HN", + "es-IC", + "es-MX", + "es-NI", + "es-PA", + "es-PE", + "es-PH", + "es-PR", + "es-PY", + "es-SV", + "es-US", + "es-UY", + "es-VE", + "et", + "et-EE", + "eu", + "eu-ES", + "fa", + "fa-AF", + "fa-IR", + "ff", + "ff-SN", + "fi", + "fi-FI", + "fr", + "fr-BE", + "fr-BF", + "fr-BI", + "fr-BJ", + "fr-BL", + "fr-CA", + "fr-CD", + "fr-CF", + "fr-CG", + "fr-CH", + "fr-CI", + "fr-CM", + "fr-DJ", + "fr-DZ", + "fr-FR", + "fr-GA", + "fr-GF", + "fr-GN", + "fr-GP", + "fr-GQ", + "fr-HT", + "fr-KM", + "fr-LU", + "fr-MA", + "fr-MC", + "fr-MF", + "fr-MG", + "fr-ML", + "fr-MQ", + "fr-MR", + "fr-MU", + "fr-NC", + "fr-NE", + "fr-PF", + "fr-RE", + "fr-RW", + "fr-SC", + "fr-SN", + "fr-SY", + "fr-TD", + "fr-TG", + "fr-TN", + "fr-VU", + "fr-YT", + "ga", + "ga-IE", + "gl", + "gl-ES", + "gu", + "gu-IN", + "he", + "he-IL", + "hi", + "hi-IN", + "hr", + "hr-BA", + "hr-HR", + "hu", + "hu-HU", + "hy", + "hy-AM", + "id", + "id-ID", + "is", + "is-IS", + "it", + "it-CH", + "it-IT", + "it-SM", + "ja", + "ja-JP", + "kk", + "kk-Cyrl", + "kk-Cyrl-KZ", + "km", + "km-KH", + "kn", + "kn-IN", + "ko", + "ko-KP", + "ko-KR", + "lt", + "lt-LT", + "lv", + "lv-LV", + "mk", + "mk-MK", + "ml", + "ml-IN", + "mr", + "mr-IN", + "nb", + "nb-NO", + "nl", + "nl-AW", + "nl-BE", + "nl-CW", + "nl-NL", + "nl-SR", + "nl-SX", + "nn", + "nn-NO", + "or", + "or-IN", + "pa", + "pa-Arab", + "pa-Arab-PK", + "pa-Guru", + "pa-Guru-IN", + "pl", + "pl-PL", + "pt", + "pt-AO", + "pt-BR", + "pt-CV", + "pt-GW", + "pt-MO", + "pt-MZ", + "pt-PT", + "pt-ST", + "pt-TL", + "rm", + "rm-CH", + "ro", + "ro-MD", + "ro-RO", + "ru", + "ru-BY", + "ru-KG", + "ru-KZ", + "ru-MD", + "ru-RU", + "ru-UA", + "si", + "si-LK", + "sk", + "sk-SK", + "sl", + "sl-SI", + "sq", + "sq-AL", + "sq-MK", + "sr", + "sr-Cyrl", + "sr-Cyrl-BA", + "sr-Cyrl-ME", + "sr-Cyrl-RS", + "sr-Latn", + "sr-Latn-BA", + "sr-Latn-ME", + "sr-Latn-RS", + "sv", + "sv-AX", + "sv-FI", + "sv-SE", + "te", + "te-IN", + "th", + "th-TH", + "tr", + "tr-CY", + "tr-TR", + "uk", + "uk-UA", + "vi", + "vi-VN", + "zh", + "zh-Hans", + "zh-Hans-CN", + "zh-Hans-HK", + "zh-Hans-MO", + "zh-Hans-SG", + "zh-Hant", + "zh-Hant-HK", + "zh-Hant-MO", + "zh-Hant-TW", +]; + +var count = Intl.DateTimeFormat.supportedLocalesOf(locales).length; + +reportCompare(locales.length, count, "Number of supported locales in Intl.DateTimeFormat"); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/timeZone.js b/js/src/tests/non262/Intl/DateTimeFormat/timeZone.js new file mode 100644 index 0000000000..eca6ed27ee --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/timeZone.js @@ -0,0 +1,139 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const tzMapper = [ + x => x, + x => x.toUpperCase(), + x => x.toLowerCase(), +]; + + +const utcTimeZones = [ + // Etc/UTC and Etc/GMT are normalized to UTC. + "Etc/UTC", "Etc/GMT", + + // Links to Etc/GMT. (tzdata/etcetera) + "GMT", "Etc/Greenwich", "Etc/GMT-0", "Etc/GMT+0", "Etc/GMT0", + + // Links to Etc/UTC. (tzdata/etcetera) + "Etc/Universal", "Etc/Zulu", + + // Links to Etc/GMT. (tzdata/backward) + "GMT+0", "GMT-0", "GMT0", "Greenwich", + + // Links to Etc/UTC. (tzdata/backward) + "UTC", "Universal", "Zulu", "Etc/UCT", "UCT", +]; + +for (let timeZone of utcTimeZones) { + for (let map of tzMapper) { + let dtf = new Intl.DateTimeFormat(undefined, {timeZone: map(timeZone)}); + assertEq(dtf.resolvedOptions().timeZone, "UTC"); + } +} + + +const invalidTimeZones = [ + "", "null", "undefined", "UTC\0", + + // ICU time zone name for invalid time zones. + "Etc/Unknown", + + // ICU custom time zones. + "GMT-1", "GMT+1", "GMT-10", "GMT+10", + "GMT-10:00", "GMT+10:00", + "GMT-1000", "GMT+1000", + + // Legacy ICU time zones. + "ACT", "AET", "AGT", "ART", "AST", "BET", "BST", "CAT", "CNT", "CST", + "CTT", "EAT", "ECT", "IET", "IST", "JST", "MIT", "NET", "NST", "PLT", + "PNT", "PRT", "PST", "SST", "VST", + + // Deprecated IANA time zones. + "SystemV/AST4ADT", "SystemV/EST5EDT", "SystemV/CST6CDT", "SystemV/MST7MDT", + "SystemV/PST8PDT", "SystemV/YST9YDT", "SystemV/AST4", "SystemV/EST5", + "SystemV/CST6", "SystemV/MST7", "SystemV/PST8", "SystemV/YST9", "SystemV/HST10", +]; + +for (let timeZone of invalidTimeZones) { + for (let map of tzMapper) { + assertThrowsInstanceOf(() => { + new Intl.DateTimeFormat(undefined, {timeZone: map(timeZone)}); + }, RangeError); + } +} + + +// GMT[+-]hh is invalid, but Etc/GMT[+-]hh is a valid IANA time zone. +for (let gmtOffset = -14; gmtOffset <= 12; ++gmtOffset) { + // Skip Etc/GMT0. + if (gmtOffset === 0) + continue; + + let timeZone = `Etc/GMT${gmtOffset > 0 ? "+" : ""}${gmtOffset}`; + for (let map of tzMapper) { + let dtf = new Intl.DateTimeFormat(undefined, {timeZone: map(timeZone)}); + assertEq(dtf.resolvedOptions().timeZone, timeZone); + } +} + + +const invalidEtcGMTNames = [ + // Out of bounds GMT offset. + "Etc/GMT-15", "Etc/GMT+13", + + // Etc/GMT[+-]hh:mm isn't a IANA time zone name. + "Etc/GMT-10:00", "Etc/GMT+10:00", + "Etc/GMT-1000", "Etc/GMT+1000", +]; + +for (let timeZone of invalidEtcGMTNames) { + for (let map of tzMapper) { + assertThrowsInstanceOf(() => { + new Intl.DateTimeFormat(undefined, {timeZone: map(timeZone)}); + }, RangeError); + } +} + + +// RangeError is thrown for primitive values, because ToString() +// isn't a valid time zone name. +for (let nonStrings of [null, 0, 0.5, true, false]) { + assertThrowsInstanceOf(() => { + new Intl.DateTimeFormat(undefined, {timeZone: nonStrings}); + }, RangeError); +} + +// ToString() throws TypeError. +assertThrowsInstanceOf(() => { + new Intl.DateTimeFormat(undefined, {timeZone: Symbol()}); +}, TypeError); + +// |undefined| or absent "timeZone" option selects the default time zone. +{ + let {timeZone: tzAbsent} = new Intl.DateTimeFormat(undefined, {}).resolvedOptions(); + let {timeZone: tzUndefined} = new Intl.DateTimeFormat(undefined, {timeZone: undefined}).resolvedOptions(); + + assertEq(typeof tzAbsent, "string"); + assertEq(typeof tzUndefined, "string"); + assertEq(tzUndefined, tzAbsent); + + // The default time zone isn't a link name. + let {timeZone: tzDefault} = new Intl.DateTimeFormat(undefined, {timeZone: tzAbsent}).resolvedOptions(); + assertEq(tzDefault, tzAbsent); +} + +// Objects are converted through ToString(). +{ + let timeZone = "Europe/Warsaw"; + let obj = { + toString() { + return timeZone; + } + }; + let dtf = new Intl.DateTimeFormat(undefined, {timeZone: obj}); + assertEq(dtf.resolvedOptions().timeZone, timeZone); +} + + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/timeZone_backward_links.js b/js/src/tests/non262/Intl/DateTimeFormat/timeZone_backward_links.js new file mode 100644 index 0000000000..5f10b8f65e --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/timeZone_backward_links.js @@ -0,0 +1,156 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Generated by make_intl_data.py. DO NOT EDIT. +// tzdata version = 2024a + +const tzMapper = [ + x => x, + x => x.toUpperCase(), + x => x.toLowerCase(), +]; + +// Link names derived from IANA Time Zone Database, backward file. +const links = { + "Africa/Asmera": "Africa/Asmara", + "America/Atka": "America/Adak", + "America/Buenos_Aires": "America/Argentina/Buenos_Aires", + "America/Catamarca": "America/Argentina/Catamarca", + "America/Cordoba": "America/Argentina/Cordoba", + "America/Fort_Wayne": "America/Indiana/Indianapolis", + "America/Godthab": "America/Nuuk", + "America/Indianapolis": "America/Indiana/Indianapolis", + "America/Jujuy": "America/Argentina/Jujuy", + "America/Knox_IN": "America/Indiana/Knox", + "America/Kralendijk": "America/Curacao", + "America/Louisville": "America/Kentucky/Louisville", + "America/Lower_Princes": "America/Curacao", + "America/Marigot": "America/Port_of_Spain", + "America/Mendoza": "America/Argentina/Mendoza", + "America/Porto_Acre": "America/Rio_Branco", + "America/Santa_Isabel": "America/Tijuana", + "America/Shiprock": "America/Denver", + "America/St_Barthelemy": "America/Port_of_Spain", + "America/Virgin": "America/St_Thomas", + "Antarctica/South_Pole": "Antarctica/McMurdo", + "Arctic/Longyearbyen": "Europe/Oslo", + "Asia/Ashkhabad": "Asia/Ashgabat", + "Asia/Calcutta": "Asia/Kolkata", + "Asia/Chungking": "Asia/Chongqing", + "Asia/Dacca": "Asia/Dhaka", + "Asia/Istanbul": "Europe/Istanbul", + "Asia/Katmandu": "Asia/Kathmandu", + "Asia/Macao": "Asia/Macau", + "Asia/Rangoon": "Asia/Yangon", + "Asia/Saigon": "Asia/Ho_Chi_Minh", + "Asia/Thimbu": "Asia/Thimphu", + "Asia/Ujung_Pandang": "Asia/Makassar", + "Asia/Ulan_Bator": "Asia/Ulaanbaatar", + "Atlantic/Faeroe": "Atlantic/Faroe", + "Australia/ACT": "Australia/Sydney", + "Australia/Canberra": "Australia/Sydney", + "Australia/LHI": "Australia/Lord_Howe", + "Australia/NSW": "Australia/Sydney", + "Australia/North": "Australia/Darwin", + "Australia/Queensland": "Australia/Brisbane", + "Australia/South": "Australia/Adelaide", + "Australia/Tasmania": "Australia/Hobart", + "Australia/Victoria": "Australia/Melbourne", + "Australia/West": "Australia/Perth", + "Australia/Yancowinna": "Australia/Broken_Hill", + "Brazil/Acre": "America/Rio_Branco", + "Brazil/DeNoronha": "America/Noronha", + "Brazil/East": "America/Sao_Paulo", + "Brazil/West": "America/Manaus", + "Canada/Atlantic": "America/Halifax", + "Canada/Central": "America/Winnipeg", + "Canada/Eastern": "America/Toronto", + "Canada/Mountain": "America/Edmonton", + "Canada/Newfoundland": "America/St_Johns", + "Canada/Pacific": "America/Vancouver", + "Canada/Saskatchewan": "America/Regina", + "Canada/Yukon": "America/Whitehorse", + "Chile/Continental": "America/Santiago", + "Chile/EasterIsland": "Pacific/Easter", + "Cuba": "America/Havana", + "Egypt": "Africa/Cairo", + "Eire": "Europe/Dublin", + "Etc/GMT+0": "Etc/GMT", + "Etc/GMT-0": "Etc/GMT", + "Etc/GMT0": "Etc/GMT", + "Etc/Greenwich": "Etc/GMT", + "Etc/UCT": "Etc/UTC", + "Etc/Universal": "Etc/UTC", + "Etc/Zulu": "Etc/UTC", + "Europe/Bratislava": "Europe/Prague", + "Europe/Busingen": "Europe/Zurich", + "Europe/Kiev": "Europe/Kyiv", + "Europe/Mariehamn": "Europe/Helsinki", + "Europe/Nicosia": "Asia/Nicosia", + "Europe/Podgorica": "Europe/Belgrade", + "Europe/San_Marino": "Europe/Rome", + "Europe/Vatican": "Europe/Rome", + "GB": "Europe/London", + "GB-Eire": "Europe/London", + "GMT+0": "Etc/GMT", + "GMT-0": "Etc/GMT", + "GMT0": "Etc/GMT", + "Greenwich": "Etc/GMT", + "Hongkong": "Asia/Hong_Kong", + "Iceland": "Atlantic/Reykjavik", + "Iran": "Asia/Tehran", + "Israel": "Asia/Jerusalem", + "Jamaica": "America/Jamaica", + "Japan": "Asia/Tokyo", + "Kwajalein": "Pacific/Kwajalein", + "Libya": "Africa/Tripoli", + "Mexico/BajaNorte": "America/Tijuana", + "Mexico/BajaSur": "America/Mazatlan", + "Mexico/General": "America/Mexico_City", + "NZ": "Pacific/Auckland", + "NZ-CHAT": "Pacific/Chatham", + "Navajo": "America/Denver", + "PRC": "Asia/Shanghai", + "Pacific/Ponape": "Pacific/Pohnpei", + "Pacific/Samoa": "Pacific/Pago_Pago", + "Pacific/Truk": "Pacific/Chuuk", + "Pacific/Yap": "Pacific/Chuuk", + "Poland": "Europe/Warsaw", + "Portugal": "Europe/Lisbon", + "ROC": "Asia/Taipei", + "ROK": "Asia/Seoul", + "Singapore": "Asia/Singapore", + "Turkey": "Europe/Istanbul", + "UCT": "Etc/UTC", + "US/Alaska": "America/Anchorage", + "US/Aleutian": "America/Adak", + "US/Arizona": "America/Phoenix", + "US/Central": "America/Chicago", + "US/East-Indiana": "America/Indiana/Indianapolis", + "US/Eastern": "America/New_York", + "US/Hawaii": "Pacific/Honolulu", + "US/Indiana-Starke": "America/Indiana/Knox", + "US/Michigan": "America/Detroit", + "US/Mountain": "America/Denver", + "US/Pacific": "America/Los_Angeles", + "US/Samoa": "Pacific/Pago_Pago", + "UTC": "Etc/UTC", + "Universal": "Etc/UTC", + "W-SU": "Europe/Moscow", + "Zulu": "Etc/UTC", +}; + +for (let [linkName, target] of Object.entries(links)) { + if (target === "Etc/UTC" || target === "Etc/GMT") + target = "UTC"; + + for (let map of tzMapper) { + let dtf = new Intl.DateTimeFormat(undefined, {timeZone: map(linkName)}); + let resolvedTimeZone = dtf.resolvedOptions().timeZone; + assertEq(resolvedTimeZone, target, `${linkName} -> ${target}`); + } +} + + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); + diff --git a/js/src/tests/non262/Intl/DateTimeFormat/timeZone_backzone.js b/js/src/tests/non262/Intl/DateTimeFormat/timeZone_backzone.js new file mode 100644 index 0000000000..15e5e6af4b --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/timeZone_backzone.js @@ -0,0 +1,152 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Generated by make_intl_data.py. DO NOT EDIT. +// tzdata version = 2024a + +const tzMapper = [ + x => x, + x => x.toUpperCase(), + x => x.toLowerCase(), +]; + +// This file was generated with historical, pre-1970 backzone information +// respected. Therefore, every zone key listed below is its own Zone, not +// a Link to a modern-day target as IANA ignoring backzones would say. + +// Backzone zones derived from IANA Time Zone Database. +const links = { + "Africa/Accra": "Africa/Accra", + "Africa/Addis_Ababa": "Africa/Addis_Ababa", + "Africa/Asmara": "Africa/Asmara", + "Africa/Bamako": "Africa/Bamako", + "Africa/Bangui": "Africa/Bangui", + "Africa/Banjul": "Africa/Banjul", + "Africa/Blantyre": "Africa/Blantyre", + "Africa/Brazzaville": "Africa/Brazzaville", + "Africa/Bujumbura": "Africa/Bujumbura", + "Africa/Conakry": "Africa/Conakry", + "Africa/Dakar": "Africa/Dakar", + "Africa/Dar_es_Salaam": "Africa/Dar_es_Salaam", + "Africa/Djibouti": "Africa/Djibouti", + "Africa/Douala": "Africa/Douala", + "Africa/Freetown": "Africa/Freetown", + "Africa/Gaborone": "Africa/Gaborone", + "Africa/Harare": "Africa/Harare", + "Africa/Kampala": "Africa/Kampala", + "Africa/Kigali": "Africa/Kigali", + "Africa/Kinshasa": "Africa/Kinshasa", + "Africa/Libreville": "Africa/Libreville", + "Africa/Lome": "Africa/Lome", + "Africa/Luanda": "Africa/Luanda", + "Africa/Lubumbashi": "Africa/Lubumbashi", + "Africa/Lusaka": "Africa/Lusaka", + "Africa/Malabo": "Africa/Malabo", + "Africa/Maseru": "Africa/Maseru", + "Africa/Mbabane": "Africa/Mbabane", + "Africa/Mogadishu": "Africa/Mogadishu", + "Africa/Niamey": "Africa/Niamey", + "Africa/Nouakchott": "Africa/Nouakchott", + "Africa/Ouagadougou": "Africa/Ouagadougou", + "Africa/Porto-Novo": "Africa/Porto-Novo", + "Africa/Timbuktu": "Africa/Timbuktu", + "America/Anguilla": "America/Anguilla", + "America/Antigua": "America/Antigua", + "America/Argentina/ComodRivadavia": "America/Argentina/ComodRivadavia", + "America/Aruba": "America/Aruba", + "America/Atikokan": "America/Atikokan", + "America/Blanc-Sablon": "America/Blanc-Sablon", + "America/Cayman": "America/Cayman", + "America/Coral_Harbour": "America/Coral_Harbour", + "America/Creston": "America/Creston", + "America/Curacao": "America/Curacao", + "America/Dominica": "America/Dominica", + "America/Ensenada": "America/Ensenada", + "America/Grenada": "America/Grenada", + "America/Guadeloupe": "America/Guadeloupe", + "America/Montreal": "America/Montreal", + "America/Montserrat": "America/Montserrat", + "America/Nassau": "America/Nassau", + "America/Nipigon": "America/Nipigon", + "America/Pangnirtung": "America/Pangnirtung", + "America/Port_of_Spain": "America/Port_of_Spain", + "America/Rainy_River": "America/Rainy_River", + "America/Rosario": "America/Rosario", + "America/St_Kitts": "America/St_Kitts", + "America/St_Lucia": "America/St_Lucia", + "America/St_Thomas": "America/St_Thomas", + "America/St_Vincent": "America/St_Vincent", + "America/Thunder_Bay": "America/Thunder_Bay", + "America/Tortola": "America/Tortola", + "America/Yellowknife": "America/Yellowknife", + "Antarctica/DumontDUrville": "Antarctica/DumontDUrville", + "Antarctica/McMurdo": "Antarctica/McMurdo", + "Antarctica/Syowa": "Antarctica/Syowa", + "Asia/Aden": "Asia/Aden", + "Asia/Bahrain": "Asia/Bahrain", + "Asia/Brunei": "Asia/Brunei", + "Asia/Chongqing": "Asia/Chongqing", + "Asia/Harbin": "Asia/Harbin", + "Asia/Kashgar": "Asia/Kashgar", + "Asia/Kuala_Lumpur": "Asia/Kuala_Lumpur", + "Asia/Kuwait": "Asia/Kuwait", + "Asia/Muscat": "Asia/Muscat", + "Asia/Phnom_Penh": "Asia/Phnom_Penh", + "Asia/Tel_Aviv": "Asia/Tel_Aviv", + "Asia/Vientiane": "Asia/Vientiane", + "Atlantic/Jan_Mayen": "Atlantic/Jan_Mayen", + "Atlantic/Reykjavik": "Atlantic/Reykjavik", + "Atlantic/St_Helena": "Atlantic/St_Helena", + "Australia/Currie": "Australia/Currie", + "Europe/Amsterdam": "Europe/Amsterdam", + "Europe/Belfast": "Europe/Belfast", + "Europe/Copenhagen": "Europe/Copenhagen", + "Europe/Guernsey": "Europe/Guernsey", + "Europe/Isle_of_Man": "Europe/Isle_of_Man", + "Europe/Jersey": "Europe/Jersey", + "Europe/Ljubljana": "Europe/Ljubljana", + "Europe/Luxembourg": "Europe/Luxembourg", + "Europe/Monaco": "Europe/Monaco", + "Europe/Oslo": "Europe/Oslo", + "Europe/Sarajevo": "Europe/Sarajevo", + "Europe/Skopje": "Europe/Skopje", + "Europe/Stockholm": "Europe/Stockholm", + "Europe/Tiraspol": "Europe/Tiraspol", + "Europe/Uzhgorod": "Europe/Uzhgorod", + "Europe/Vaduz": "Europe/Vaduz", + "Europe/Zagreb": "Europe/Zagreb", + "Europe/Zaporozhye": "Europe/Zaporozhye", + "Indian/Antananarivo": "Indian/Antananarivo", + "Indian/Christmas": "Indian/Christmas", + "Indian/Cocos": "Indian/Cocos", + "Indian/Comoro": "Indian/Comoro", + "Indian/Kerguelen": "Indian/Kerguelen", + "Indian/Mahe": "Indian/Mahe", + "Indian/Mayotte": "Indian/Mayotte", + "Indian/Reunion": "Indian/Reunion", + "Pacific/Chuuk": "Pacific/Chuuk", + "Pacific/Enderbury": "Pacific/Enderbury", + "Pacific/Funafuti": "Pacific/Funafuti", + "Pacific/Johnston": "Pacific/Johnston", + "Pacific/Majuro": "Pacific/Majuro", + "Pacific/Midway": "Pacific/Midway", + "Pacific/Pohnpei": "Pacific/Pohnpei", + "Pacific/Saipan": "Pacific/Saipan", + "Pacific/Wake": "Pacific/Wake", + "Pacific/Wallis": "Pacific/Wallis", +}; + +for (let [linkName, target] of Object.entries(links)) { + if (target === "Etc/UTC" || target === "Etc/GMT") + target = "UTC"; + + for (let map of tzMapper) { + let dtf = new Intl.DateTimeFormat(undefined, {timeZone: map(linkName)}); + let resolvedTimeZone = dtf.resolvedOptions().timeZone; + assertEq(resolvedTimeZone, target, `${linkName} -> ${target}`); + } +} + + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); + diff --git a/js/src/tests/non262/Intl/DateTimeFormat/timeZone_backzone_links.js b/js/src/tests/non262/Intl/DateTimeFormat/timeZone_backzone_links.js new file mode 100644 index 0000000000..df3e6c58af --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/timeZone_backzone_links.js @@ -0,0 +1,48 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Generated by make_intl_data.py. DO NOT EDIT. +// tzdata version = 2024a + +const tzMapper = [ + x => x, + x => x.toUpperCase(), + x => x.toLowerCase(), +]; + +// This file was generated with historical, pre-1970 backzone information +// respected. Therefore, every zone key listed below points to a target +// in the backzone file and not to its modern-day target as IANA ignoring +// backzones would say. + +// Backzone links derived from IANA Time Zone Database. +const links = { + "Africa/Asmera": "Africa/Asmara", + "America/Kralendijk": "America/Curacao", + "America/Lower_Princes": "America/Curacao", + "America/Marigot": "America/Port_of_Spain", + "America/St_Barthelemy": "America/Port_of_Spain", + "America/Virgin": "America/St_Thomas", + "Antarctica/South_Pole": "Antarctica/McMurdo", + "Arctic/Longyearbyen": "Europe/Oslo", + "Asia/Chungking": "Asia/Chongqing", + "Iceland": "Atlantic/Reykjavik", + "Pacific/Ponape": "Pacific/Pohnpei", + "Pacific/Truk": "Pacific/Chuuk", + "Pacific/Yap": "Pacific/Chuuk", +}; + +for (let [linkName, target] of Object.entries(links)) { + if (target === "Etc/UTC" || target === "Etc/GMT") + target = "UTC"; + + for (let map of tzMapper) { + let dtf = new Intl.DateTimeFormat(undefined, {timeZone: map(linkName)}); + let resolvedTimeZone = dtf.resolvedOptions().timeZone; + assertEq(resolvedTimeZone, target, `${linkName} -> ${target}`); + } +} + + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); + diff --git a/js/src/tests/non262/Intl/DateTimeFormat/timeZone_notbackward_links.js b/js/src/tests/non262/Intl/DateTimeFormat/timeZone_notbackward_links.js new file mode 100644 index 0000000000..864505f546 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/timeZone_notbackward_links.js @@ -0,0 +1,31 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Generated by make_intl_data.py. DO NOT EDIT. +// tzdata version = 2024a + +const tzMapper = [ + x => x, + x => x.toUpperCase(), + x => x.toLowerCase(), +]; + +// Link names derived from IANA Time Zone Database, excluding backward file. +const links = { + "GMT": "Etc/GMT", +}; + +for (let [linkName, target] of Object.entries(links)) { + if (target === "Etc/UTC" || target === "Etc/GMT") + target = "UTC"; + + for (let map of tzMapper) { + let dtf = new Intl.DateTimeFormat(undefined, {timeZone: map(linkName)}); + let resolvedTimeZone = dtf.resolvedOptions().timeZone; + assertEq(resolvedTimeZone, target, `${linkName} -> ${target}`); + } +} + + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); + diff --git a/js/src/tests/non262/Intl/DateTimeFormat/timeZone_version.js b/js/src/tests/non262/Intl/DateTimeFormat/timeZone_version.js new file mode 100644 index 0000000000..915b1537ca --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/timeZone_version.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Generated by make_intl_data.py. DO NOT EDIT. +// tzdata version = 2024a +const tzdata = "2024a"; + +if (typeof getICUOptions === "undefined") { + var getICUOptions = SpecialPowers.Cu.getJSTestingFunctions().getICUOptions; +} + +var options = getICUOptions(); + +assertEq(options.tzdata, tzdata); + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); + diff --git a/js/src/tests/non262/Intl/DateTimeFormat/toStringTag.js b/js/src/tests/non262/Intl/DateTimeFormat/toStringTag.js new file mode 100644 index 0000000000..136632f71f --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/toStringTag.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var desc = Object.getOwnPropertyDescriptor(Intl.DateTimeFormat.prototype, Symbol.toStringTag); + +assertEq(desc !== undefined, true); +assertEq(desc.value, "Intl.DateTimeFormat"); +assertEq(desc.writable, false); +assertEq(desc.enumerable, false); +assertEq(desc.configurable, true); + +assertEq(Object.prototype.toString.call(Intl.DateTimeFormat.prototype), "[object Intl.DateTimeFormat]"); +assertEq(Object.prototype.toString.call(new Intl.DateTimeFormat), "[object Intl.DateTimeFormat]"); + +Object.defineProperty(Intl.DateTimeFormat.prototype, Symbol.toStringTag, {value: "DateTimeFormat"}); + +assertEq(Object.prototype.toString.call(Intl.DateTimeFormat.prototype), "[object DateTimeFormat]"); +assertEq(Object.prototype.toString.call(new Intl.DateTimeFormat), "[object DateTimeFormat]"); + +delete Intl.DateTimeFormat.prototype[Symbol.toStringTag]; + +assertEq(Object.prototype.toString.call(Intl.DateTimeFormat.prototype), "[object Object]"); +assertEq(Object.prototype.toString.call(new Intl.DateTimeFormat), "[object Object]"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/tz-environment-variable.js b/js/src/tests/non262/Intl/DateTimeFormat/tz-environment-variable.js new file mode 100644 index 0000000000..6128abb9d1 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/tz-environment-variable.js @@ -0,0 +1,67 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")||(xulRuntime.OS=="WINNT"&&!xulRuntime.shell)) -- Windows browser in automation doesn't pick up new time zones correctly + +// From bug 1330149: +// +// Windows only supports a very limited set of IANA time zone names for the TZ +// environment variable. +// +// TZ format supported by Windows: "TZ=tzn[+|-]hh[:mm[:ss]][dzn]". +// +// Complete list of all IANA time zone ids matching that format. +// +// From tzdata's "northamerica" file: +// EST5EDT +// CST6CDT +// MST7MDT +// PST8PDT +// +// From tzdata's "backward" file: +// GMT+0 +// GMT-0 +// GMT0 +// +// Also supported on Windows even though they don't match the format listed +// above. +// +// From tzdata's "backward" file: +// UCT +// UTC +// +// From tzdata's "etcetera" file: +// GMT + +function inTimeZone(tzname, fn) { + setTimeZone(tzname); + try { + fn(); + } finally { + setTimeZone("PST8PDT"); + } +} + +const timeZones = [ + { id: "EST5EDT" }, + { id: "CST6CDT" }, + { id: "MST7MDT" }, + { id: "PST8PDT" }, + // ICU on non-Windows platforms doesn't accept these three time zone + // identifiers, cf. isValidOlsonID in $ICU/source/common/putil.cpp. We + // could add support for them, but it seems unlikely they're used in + // practice, so we just skip over them. + // { id: "GMT+0", normalized: "UTC" }, + // { id: "GMT-0", normalized: "UTC" }, + // { id: "GMT0", normalized: "UTC" }, + { id: "UCT", normalized: "UTC" }, + { id: "UTC", normalized: "UTC" }, + { id: "GMT", normalized: "UTC" }, +]; + +for (let {id, normalized = id} of timeZones) { + inTimeZone(id, () => { + let opts = new Intl.DateTimeFormat().resolvedOptions(); + assertEq(opts.timeZone, normalized); + }); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/unwrapping.js b/js/src/tests/non262/Intl/DateTimeFormat/unwrapping.js new file mode 100644 index 0000000000..d2fc991cb4 --- /dev/null +++ b/js/src/tests/non262/Intl/DateTimeFormat/unwrapping.js @@ -0,0 +1,248 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Test UnwrapDateTimeFormat operation. + +const dateTimeFormatFunctions = []; +dateTimeFormatFunctions.push({ + function: Intl.DateTimeFormat.prototype.resolvedOptions, + unwrap: true, +}); +dateTimeFormatFunctions.push({ + function: Object.getOwnPropertyDescriptor(Intl.DateTimeFormat.prototype, "format").get, + unwrap: true, +}); +dateTimeFormatFunctions.push({ + function: Intl.DateTimeFormat.prototype.formatToParts, + unwrap: false, +}); + +function IsIntlService(c) { + return typeof c === "function" && + c.hasOwnProperty("prototype") && + c.prototype.hasOwnProperty("resolvedOptions"); +} + +function IsObject(o) { + return Object(o) === o; +} + +function IsPrimitive(o) { + return Object(o) !== o; +} + +function intlObjects(ctor) { + let args = []; + if (ctor === Intl.DisplayNames) { + // Intl.DisplayNames can't be constructed without any arguments. + args = [undefined, {type: "language"}]; + } + + return [ + // Instance of an Intl constructor. + new ctor(...args), + + // Instance of a subclassed Intl constructor. + new class extends ctor {}(...args), + + // Intl object not inheriting from its default prototype. + Object.setPrototypeOf(new ctor(...args), Object.prototype), + ]; +} + +function thisValues(C) { + const intlConstructors = Object.getOwnPropertyNames(Intl).map(name => Intl[name]).filter(IsIntlService); + + return [ + // Primitive values. + ...[undefined, null, true, "abc", Symbol(), 123], + + // Object values. + ...[{}, [], /(?:)/, function(){}, new Proxy({}, {})], + + // Intl objects. + ...[].concat(...intlConstructors.filter(ctor => ctor !== C).map(intlObjects)), + + // Object inheriting from an Intl constructor prototype. + ...intlConstructors.map(ctor => Object.create(ctor.prototype)), + ]; +} + +const intlFallbackSymbol = Object.getOwnPropertySymbols(Intl.DateTimeFormat.call(Object.create(Intl.DateTimeFormat.prototype)))[0]; + +// Test Intl.DateTimeFormat.prototype methods. +for (let {function: dateTimeFormatFunction, unwrap} of dateTimeFormatFunctions) { + // Test a TypeError is thrown when the this-value isn't an initialized + // Intl.DateTimeFormat instance. + for (let thisValue of thisValues(Intl.DateTimeFormat)) { + assertThrowsInstanceOf(() => dateTimeFormatFunction.call(thisValue), TypeError); + } + + // And test no error is thrown for initialized Intl.DateTimeFormat instances. + for (let thisValue of intlObjects(Intl.DateTimeFormat)) { + dateTimeFormatFunction.call(thisValue); + } + + // Manually add [[FallbackSymbol]] to objects and then repeat the tests from above. + for (let thisValue of thisValues(Intl.DateTimeFormat)) { + assertThrowsInstanceOf(() => dateTimeFormatFunction.call({ + __proto__: Intl.DateTimeFormat.prototype, + [intlFallbackSymbol]: thisValue, + }), TypeError); + } + + for (let thisValue of intlObjects(Intl.DateTimeFormat)) { + let obj = { + __proto__: Intl.DateTimeFormat.prototype, + [intlFallbackSymbol]: thisValue, + }; + if (unwrap) { + dateTimeFormatFunction.call(obj); + } else { + assertThrowsInstanceOf(() => dateTimeFormatFunction.call(obj), TypeError); + } + } + + // Ensure [[FallbackSymbol]] isn't retrieved for Intl.DateTimeFormat instances. + for (let thisValue of intlObjects(Intl.DateTimeFormat)) { + Object.defineProperty(thisValue, intlFallbackSymbol, { + get() { assertEq(false, true); } + }); + dateTimeFormatFunction.call(thisValue); + } + + // Ensure [[FallbackSymbol]] is only retrieved for objects inheriting from Intl.DateTimeFormat.prototype. + for (let thisValue of thisValues(Intl.DateTimeFormat).filter(IsObject)) { + if (Intl.DateTimeFormat.prototype.isPrototypeOf(thisValue)) + continue; + Object.defineProperty(thisValue, intlFallbackSymbol, { + get() { assertEq(false, true); } + }); + assertThrowsInstanceOf(() => dateTimeFormatFunction.call(thisValue), TypeError); + } + + // Repeat the test from above, but also change Intl.DateTimeFormat[@@hasInstance] + // so it always returns |true|. + for (let thisValue of thisValues(Intl.DateTimeFormat).filter(IsObject)) { + let isPrototypeOf = Intl.DateTimeFormat.prototype.isPrototypeOf(thisValue); + let hasInstanceCalled = false, symbolGetterCalled = false; + Object.defineProperty(Intl.DateTimeFormat, Symbol.hasInstance, { + value() { + assertEq(hasInstanceCalled, false); + hasInstanceCalled = true; + return true; + }, configurable: true + }); + Object.defineProperty(thisValue, intlFallbackSymbol, { + get() { + assertEq(symbolGetterCalled, false); + symbolGetterCalled = true; + return null; + }, configurable: true + }); + + assertThrowsInstanceOf(() => dateTimeFormatFunction.call(thisValue), TypeError); + + delete Intl.DateTimeFormat[Symbol.hasInstance]; + + assertEq(hasInstanceCalled, false); + assertEq(symbolGetterCalled, unwrap && isPrototypeOf); + } + + // Test with primitive values. + for (let thisValue of thisValues(Intl.DateTimeFormat).filter(IsPrimitive)) { + // Ensure @@hasInstance is not called. + Object.defineProperty(Intl.DateTimeFormat, Symbol.hasInstance, { + value() { assertEq(true, false); }, configurable: true + }); + let isUndefinedOrNull = thisValue === undefined || thisValue === null; + let symbolHolder; + if (!isUndefinedOrNull) { + // Ensure the fallback symbol isn't retrieved from the primitive wrapper prototype. + symbolHolder = Object.getPrototypeOf(thisValue); + Object.defineProperty(symbolHolder, intlFallbackSymbol, { + get() { assertEq(true, false); }, configurable: true + }); + } + + assertThrowsInstanceOf(() => dateTimeFormatFunction.call(thisValue), TypeError); + + delete Intl.DateTimeFormat[Symbol.hasInstance]; + if (!isUndefinedOrNull) + delete symbolHolder[intlFallbackSymbol]; + } +} + +// Test format() returns the correct result for objects initialized as Intl.DateTimeFormat instances. +{ + // An actual Intl.DateTimeFormat instance. + let dateTimeFormat = new Intl.DateTimeFormat(); + + // An object initialized as a DateTimeFormat instance. + let thisValue = Object.create(Intl.DateTimeFormat.prototype); + Intl.DateTimeFormat.call(thisValue); + + // Object with [[FallbackSymbol]] set to DateTimeFormat instance. + let fakeObj = { + __proto__: Intl.DateTimeFormat.prototype, + [intlFallbackSymbol]: dateTimeFormat, + }; + + for (let number of [0, Date.now(), -Date.now()]) { + let expected = dateTimeFormat.format(number); + assertEq(thisValue.format(number), expected); + assertEq(thisValue[intlFallbackSymbol].format(number), expected); + assertEq(fakeObj.format(number), expected); + } +} + +// Ensure formatToParts() doesn't use the fallback semantics. +{ + let formatToParts = Intl.DateTimeFormat.prototype.formatToParts; + + // An object initialized as a DateTimeFormat instance. + let thisValue = Object.create(Intl.DateTimeFormat.prototype); + Intl.DateTimeFormat.call(thisValue); + assertThrowsInstanceOf(() => formatToParts.call(thisValue), TypeError); + + // Object with [[FallbackSymbol]] set to DateTimeFormat instance. + let fakeObj = { + __proto__: Intl.DateTimeFormat.prototype, + [intlFallbackSymbol]: new Intl.DateTimeFormat(), + }; + assertThrowsInstanceOf(() => formatToParts.call(fakeObj), TypeError); +} + +// Test resolvedOptions() returns the same results. +{ + // An actual Intl.DateTimeFormat instance. + let dateTimeFormat = new Intl.DateTimeFormat(); + + // An object initialized as a DateTimeFormat instance. + let thisValue = Object.create(Intl.DateTimeFormat.prototype); + Intl.DateTimeFormat.call(thisValue); + + // Object with [[FallbackSymbol]] set to DateTimeFormat instance. + let fakeObj = { + __proto__: Intl.DateTimeFormat.prototype, + [intlFallbackSymbol]: dateTimeFormat, + }; + + function assertEqOptions(actual, expected) { + actual = Object.entries(actual); + expected = Object.entries(expected); + + assertEq(actual.length, expected.length, "options count mismatch"); + for (var i = 0; i < expected.length; i++) { + assertEq(actual[i][0], expected[i][0], "key mismatch at " + i); + assertEq(actual[i][1], expected[i][1], "value mismatch at " + i); + } + } + + let expected = dateTimeFormat.resolvedOptions(); + assertEqOptions(thisValue.resolvedOptions(), expected); + assertEqOptions(thisValue[intlFallbackSymbol].resolvedOptions(), expected); + assertEqOptions(fakeObj.resolvedOptions(), expected); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/DisplayNames/abbreviated.js b/js/src/tests/non262/Intl/DisplayNames/abbreviated.js new file mode 100644 index 0000000000..4203ffcbac --- /dev/null +++ b/js/src/tests/non262/Intl/DisplayNames/abbreviated.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')||!this.hasOwnProperty('addIntlExtras')) + +addMozIntlDisplayNames(this); + +const tests = { + "en": { + long: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], + abbreviated: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], + short: ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"], + narrow: ["M", "T", "W", "T", "F", "S", "S"], + }, +}; + +for (let [locale, localeTests] of Object.entries(tests)) { + for (let [style, weekdays] of Object.entries(localeTests)) { + let dn = new Intl.DisplayNames(locale, {type: "weekday", style}); + + let resolved = dn.resolvedOptions(); + assertEq(resolved.style, style); + + for (let [day, expected] of weekdays.entries()) { + assertEq(dn.of(day + 1), expected); + } + } +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/DisplayNames/alias-and-parent-locales.js b/js/src/tests/non262/Intl/DisplayNames/alias-and-parent-locales.js new file mode 100644 index 0000000000..d60a1593d4 --- /dev/null +++ b/js/src/tests/non262/Intl/DisplayNames/alias-and-parent-locales.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')) + +// Ensure alias and parent locales are correctly picked up when calling into ICU. + +// "zh-HK" is an alias to "zh-Hant-HK", so display names should default to +// traditional instead of simplified characters. +{ + const zh_Hant = new Intl.DisplayNames("zh-Hant", {type: "region"}); + const zh_Hans = new Intl.DisplayNames("zh-Hans", {type: "region"}); + const zh_HK = new Intl.DisplayNames("zh-HK", {type: "region"}); + + // We assume traditional and simplified have different outputs. + assertEq(zh_Hant.of("US") === zh_Hans.of("US"), false); + + // "zh-HK" should use traditional characters. + assertEq(zh_HK.of("US"), zh_Hant.of("US")); +} + +// The parent locale of "en-AU" is "en-001" and not "en" (because "en" actually means "en-US"). +{ + const en = new Intl.DisplayNames("en", {type: "language"}); + const en_001 = new Intl.DisplayNames("en-001", {type: "language"}); + const en_AU = new Intl.DisplayNames("en-AU", {type: "language"}); + + // We assume "en" and "en-001" have different outputs. + assertEq(en.of("nds-NL") === en_001.of("nds-NL"), false); + + // "en-AU" should have the same output as "en-001". + assertEq(en_AU.of("nds-NL"), en_001.of("nds-NL")); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/DisplayNames/browser.js b/js/src/tests/non262/Intl/DisplayNames/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Intl/DisplayNames/calendar.js b/js/src/tests/non262/Intl/DisplayNames/calendar.js new file mode 100644 index 0000000000..0700ee2888 --- /dev/null +++ b/js/src/tests/non262/Intl/DisplayNames/calendar.js @@ -0,0 +1,123 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')) + +const tests = { + "en": { + long: { + "gregory": "Gregorian Calendar", + "iso8601": "ISO-8601 Calendar", + "japanese": "Japanese Calendar", + "islamic-civil": "Islamic Calendar (tabular, civil epoch)", + "islamicc": "Islamic Calendar (tabular, civil epoch)", + "ethioaa": "Ethiopic Amete Alem Calendar", + "ethiopic-amete-alem": "Ethiopic Amete Alem Calendar", + }, + short: {}, + narrow: {}, + }, + "de": { + long: { + "gregory": "Gregorianischer Kalender", + "iso8601": "ISO-8601-Kalender", + "japanese": "Japanischer Kalender", + "islamic-civil": "Bürgerlicher islamischer Kalender (tabellarisch)", + "islamicc": "Bürgerlicher islamischer Kalender (tabellarisch)", + "ethioaa": "Äthiopischer Amätä-Aläm-Kalender", + "ethiopic-amete-alem": "Äthiopischer Amätä-Aläm-Kalender", + }, + short: {}, + narrow: {}, + }, + "fr": { + long: { + "gregory": "calendrier grégorien", + "iso8601": "calendrier ISO 8601", + "japanese": "calendrier japonais", + "islamic-civil": "calendrier musulman (tabulaire, époque civile)", + "islamicc": "calendrier musulman (tabulaire, époque civile)", + "ethioaa": "calendrier éthiopien Amete Alem", + "ethiopic-amete-alem": "calendrier éthiopien Amete Alem", + }, + short: {}, + narrow: {}, + }, + "zh": { + long: { + "gregory": "公历", + "iso8601": "国际标准历法", + "japanese": "和历", + "islamic-civil": "伊斯兰希吉来日历", + "islamicc": "伊斯兰希吉来日历", + "ethioaa": "埃塞俄比亚阿米特阿莱姆日历", + "ethiopic-amete-alem": "埃塞俄比亚阿米特阿莱姆日历", + }, + short: {}, + narrow: {}, + }, +}; + +for (let [locale, localeTests] of Object.entries(tests)) { + for (let [style, styleTests] of Object.entries(localeTests)) { + let dn = new Intl.DisplayNames(locale, {type: "calendar", style}); + + let resolved = dn.resolvedOptions(); + assertEq(resolved.locale, locale); + assertEq(resolved.style, style); + assertEq(resolved.type, "calendar"); + assertEq(resolved.fallback, "code"); + + let inheritedTests = {...localeTests.long, ...localeTests.short, ...localeTests.narrow}; + for (let [calendar, expected] of Object.entries({...inheritedTests, ...styleTests})) { + assertEq(dn.of(calendar), expected); + + // Also works with objects. + assertEq(dn.of(Object(calendar)), expected); + } + } +} + +{ + let dn = new Intl.DisplayNames("en", {type: "calendar"}); + + // Performs ToString on the input and then validates the stringified result. + assertThrowsInstanceOf(() => dn.of(), RangeError); + assertThrowsInstanceOf(() => dn.of(undefined), RangeError); + assertThrowsInstanceOf(() => dn.of(Symbol()), TypeError); + assertThrowsInstanceOf(() => dn.of(0), RangeError); + + // Throws an error if |code| isn't a well-formed calendar type. + assertThrowsInstanceOf(() => dn.of("gregorian"), RangeError); + assertThrowsInstanceOf(() => dn.of("grëgory"), RangeError); + assertThrowsInstanceOf(() => dn.of("grēgory"), RangeError); +} + +// Test fallback behaviour. +{ + let dn1 = new Intl.DisplayNames("en", {type: "calendar"}); + let dn2 = new Intl.DisplayNames("en", {type: "calendar", fallback: "code"}); + let dn3 = new Intl.DisplayNames("en", {type: "calendar", fallback: "none"}); + + assertEq(dn1.resolvedOptions().fallback, "code"); + assertEq(dn2.resolvedOptions().fallback, "code"); + assertEq(dn3.resolvedOptions().fallback, "none"); + + // "invalid" isn't a known calendar type. + assertEq(dn1.of("invalid"), "invalid"); + assertEq(dn2.of("invalid"), "invalid"); + assertEq(dn3.of("invalid"), undefined); + + // The returned fallback is in canonical case. + assertEq(dn1.of("INVALID"), "invalid"); + assertEq(dn2.of("INVALID"), "invalid"); + assertEq(dn3.of("INVALID"), undefined); +} + +// Test when case isn't canonical. +{ + let dn = new Intl.DisplayNames("en", {type: "calendar", fallback: "none"}); + + assertEq(dn.of("gregory"), "Gregorian Calendar"); + assertEq(dn.of("GREGORY"), "Gregorian Calendar"); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/DisplayNames/currency.js b/js/src/tests/non262/Intl/DisplayNames/currency.js new file mode 100644 index 0000000000..1571249106 --- /dev/null +++ b/js/src/tests/non262/Intl/DisplayNames/currency.js @@ -0,0 +1,150 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')) + +const tests = { + "en": { + long: { + "USD": "US Dollar", + "EUR": "Euro", + "FRF": "French Franc", + "CNY": "Chinese Yuan", + "XAU": "Gold", + }, + short: { + "USD": "$", + "EUR": "€", + "FRF": "FRF", + "CNY": "CN¥", + "XAU": "XAU", + }, + narrow: { + "USD": "USD", + "EUR": "EUR", + "CNY": "CNY", + }, + }, + "de": { + long: { + "USD": "US-Dollar", + "EUR": "Euro", + "FRF": "Französischer Franc", + "CNY": "Renminbi Yuan", + "XAU": "Unze Gold", + }, + short: { + "USD": "$", + "EUR": "€", + "FRF": "FRF", + "CNY": "CN¥", + "XAU": "XAU", + }, + narrow: { + "CNY": "¥", + }, + }, + "fr": { + long: { + "USD": "dollar des États-Unis", + "EUR": "euro", + "FRF": "franc français", + "CNY": "yuan renminbi chinois", + "XAU": "or", + }, + short: { + "USD": "$US", + "EUR": "€", + "FRF": "F", + "CNY": "CNY", + "XAU": "XAU", + }, + narrow: { + "USD": "$", + "CNY": "¥", + }, + }, + "zh": { + long: { + "USD": "美元", + "EUR": "欧元", + "FRF": "法国法郎", + "CNY": "人民币", + "XAU": "黄金", + }, + short: { + "USD": "US$", + "EUR": "€", + "FRF": "FRF", + "CNY": "¥", + "XAU": "XAU", + }, + narrow: { + "USD": "$", + }, + }, +}; + +for (let [locale, localeTests] of Object.entries(tests)) { + for (let [style, styleTests] of Object.entries(localeTests)) { + let dn = new Intl.DisplayNames(locale, {type: "currency", style}); + + let resolved = dn.resolvedOptions(); + assertEq(resolved.locale, locale); + assertEq(resolved.style, style); + assertEq(resolved.type, "currency"); + assertEq(resolved.fallback, "code"); + + let inheritedTests = {...localeTests.long, ...localeTests.short, ...localeTests.narrow}; + for (let [currency, expected] of Object.entries({...inheritedTests, ...styleTests})) { + assertEq(dn.of(currency), expected); + + // Also works with objects. + assertEq(dn.of(Object(currency)), expected); + } + } +} + +{ + let dn = new Intl.DisplayNames("en", {type: "currency"}); + + // Performs ToString on the input and then validates the stringified result. + assertThrowsInstanceOf(() => dn.of(), RangeError); + assertThrowsInstanceOf(() => dn.of(null), RangeError); + assertThrowsInstanceOf(() => dn.of(Symbol()), TypeError); + assertThrowsInstanceOf(() => dn.of(0), RangeError); + + // Throws an error if |code| isn't a well-formed currency code. + assertThrowsInstanceOf(() => dn.of("us"), RangeError); + assertThrowsInstanceOf(() => dn.of("euro"), RangeError); + assertThrowsInstanceOf(() => dn.of("€uro"), RangeError); +} + +// Test fallback behaviour. +{ + let dn1 = new Intl.DisplayNames("en", {type: "currency"}); + let dn2 = new Intl.DisplayNames("en", {type: "currency", fallback: "code"}); + let dn3 = new Intl.DisplayNames("en", {type: "currency", fallback: "none"}); + + assertEq(dn1.resolvedOptions().fallback, "code"); + assertEq(dn2.resolvedOptions().fallback, "code"); + assertEq(dn3.resolvedOptions().fallback, "none"); + + // "AAA" is not a registered currency code. + assertEq(dn1.of("AAA"), "AAA"); + assertEq(dn2.of("AAA"), "AAA"); + assertEq(dn3.of("AAA"), undefined); + + // The returned fallback is in canonical case. + assertEq(dn1.of("aaa"), "AAA"); + assertEq(dn2.of("aaa"), "AAA"); + assertEq(dn3.of("aaa"), undefined); +} + +// Test when case isn't canonical. +{ + let dn = new Intl.DisplayNames("en", {type: "currency", fallback: "none"}); + + assertEq(dn.of("USD"), "US Dollar"); + assertEq(dn.of("usd"), "US Dollar"); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/DisplayNames/dateTimeField.js b/js/src/tests/non262/Intl/DisplayNames/dateTimeField.js new file mode 100644 index 0000000000..94bdf53899 --- /dev/null +++ b/js/src/tests/non262/Intl/DisplayNames/dateTimeField.js @@ -0,0 +1,176 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')) + +const tests = { + "en": { + long: { + "era": "era", + "year": "year", + "quarter": "quarter", + "month": "month", + "weekOfYear": "week", + "weekday": "day of the week", + "day": "day", + "dayPeriod": "AM/PM", + "hour": "hour", + "minute": "minute", + "second": "second", + "timeZoneName": "time zone", + }, + short: { + "year": "yr.", + "quarter": "qtr.", + "month": "mo.", + "weekOfYear": "wk.", + "weekday": "day of wk.", + "dayPeriod": "AM/PM", + "hour": "hr.", + "minute": "min.", + "second": "sec.", + "timeZoneName": "zone", + }, + narrow: { + "year": "yr", + "quarter": "qtr", + "month": "mo", + "weekOfYear": "wk", + "hour": "hr", + "minute": "min", + "second": "sec", + }, + }, + "de": { + long: { + "era": "Epoche", + "year": "Jahr", + "quarter": "Quartal", + "month": "Monat", + "weekOfYear": "Woche", + "weekday": "Wochentag", + "day": "Tag", + "dayPeriod": "Tageshälfte", + "hour": "Stunde", + "minute": "Minute", + "second": "Sekunde", + "timeZoneName": "Zeitzone", + }, + short: { + "era": "Epoche", + "year": "Jahr", + "quarter": "Quart.", + "month": "Monat", + "weekOfYear": "Woche", + "weekday": "Wochentag", + "day": "Tag", + "dayPeriod": "Tageshälfte", + "hour": "Std.", + "minute": "Min.", + "second": "Sek.", + "timeZoneName": "Zeitzone", + }, + narrow: { + "era": "E", + "year": "J", + "quarter": "Q", + "month": "M", + "weekOfYear": "W", + "weekday": "Wochent.", + "dayPeriod": "Tagesh.", + "timeZoneName": "Zeitz.", + }, + }, + "fr": { + long: { + "era": "ère", + "year": "année", + "quarter": "trimestre", + "month": "mois", + "weekOfYear": "semaine", + "weekday": "jour de la semaine", + "day": "jour", + "dayPeriod": "cadran", + "hour": "heure", + "minute": "minute", + "second": "seconde", + "timeZoneName": "fuseau horaire", + }, + short: { + "year": "an", + "quarter": "trim.", + "month": "m.", + "weekOfYear": "sem.", + "weekday": "j (sem.)", + "day": "j", + "hour": "h", + "minute": "min", + "second": "s", + }, + narrow: { + "year": "a", + }, + }, + "zh": { + long: { + "era": "纪元", + "year": "年", + "quarter": "季度", + "month": "月", + "weekOfYear": "周", + "weekday": "工作日", + "day": "日", + "dayPeriod": "上午/下午", + "hour": "小时", + "minute": "分钟", + "second": "秒", + "timeZoneName": "时区", + }, + short: { + "quarter": "季", + "minute": "分", + }, + narrow: {}, + }, +}; + +for (let [locale, localeTests] of Object.entries(tests)) { + for (let [style, styleTests] of Object.entries(localeTests)) { + let dn = new Intl.DisplayNames(locale, {type: "dateTimeField", style}); + + let resolved = dn.resolvedOptions(); + assertEq(resolved.locale, locale); + assertEq(resolved.style, style); + assertEq(resolved.type, "dateTimeField"); + assertEq(resolved.fallback, "code"); + + let inheritedTests = {...localeTests.long, ...localeTests.short, ...localeTests.narrow}; + for (let [field, expected] of Object.entries({...inheritedTests, ...styleTests})) { + assertEq(dn.of(field), expected); + + // Also works with objects. + assertEq(dn.of(Object(field)), expected); + } + } +} + +{ + let dn = new Intl.DisplayNames("en", {type: "dateTimeField"}); + + // Performs ToString on the input and then validates the stringified result. + assertThrowsInstanceOf(() => dn.of(), RangeError); + assertThrowsInstanceOf(() => dn.of(null), RangeError); + assertThrowsInstanceOf(() => dn.of(Symbol()), TypeError); + assertThrowsInstanceOf(() => dn.of(0), RangeError); + assertThrowsInstanceOf(() => dn.of(1), RangeError); + + // Throws an error if not one of ["era", "year", "quarter", "month", "weekOfYear", "weekday", + // "day", "dayPeriod", "hour", "minute", "second", "timeZoneName"]. + assertThrowsInstanceOf(() => dn.of(""), RangeError); + assertThrowsInstanceOf(() => dn.of("ERA"), RangeError); + assertThrowsInstanceOf(() => dn.of("Era"), RangeError); + assertThrowsInstanceOf(() => dn.of("era\0"), RangeError); + assertThrowsInstanceOf(() => dn.of("dayperiod"), RangeError); + assertThrowsInstanceOf(() => dn.of("day-period"), RangeError); + assertThrowsInstanceOf(() => dn.of("timezoneName"), RangeError); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/DisplayNames/dayPeriod.js b/js/src/tests/non262/Intl/DisplayNames/dayPeriod.js new file mode 100644 index 0000000000..cfeafdf5ee --- /dev/null +++ b/js/src/tests/non262/Intl/DisplayNames/dayPeriod.js @@ -0,0 +1,80 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')||!this.hasOwnProperty('addIntlExtras')) + +addMozIntlDisplayNames(this); + +const tests = { + "en": { + long: { + "am": "AM", + "pm": "PM", + }, + short: {}, + narrow: {}, + }, + "de": { + long: { + "am": "AM", + "pm": "PM", + }, + short: {}, + narrow: {}, + }, + "fr": { + long: { + "am": "AM", + "pm": "PM", + }, + short: {}, + narrow: {}, + }, + "zh": { + long: { + "am": "上午", + "pm": "下午", + }, + short: {}, + narrow: {}, + }, +}; + +for (let [locale, localeTests] of Object.entries(tests)) { + let defaultCalendar = new Intl.DateTimeFormat(locale).resolvedOptions().calendar; + + for (let [style, styleTests] of Object.entries(localeTests)) { + let dn = new Intl.DisplayNames(locale, {type: "dayPeriod", style}); + + let resolved = dn.resolvedOptions(); + assertEq(resolved.locale, locale); + assertEq(resolved.calendar, defaultCalendar); + assertEq(resolved.style, style); + assertEq(resolved.type, "dayPeriod"); + assertEq(resolved.fallback, "code"); + + let inheritedTests = {...localeTests.long, ...localeTests.short, ...localeTests.narrow}; + for (let [dayPeriod, expected] of Object.entries({...inheritedTests, ...styleTests})) { + assertEq(dn.of(dayPeriod), expected); + + // Also works with objects. + assertEq(dn.of(Object(dayPeriod)), expected); + } + } +} + +{ + let dn = new Intl.DisplayNames("en", {type: "dayPeriod"}); + + // Performs ToString on the input and then validates the stringified result. + assertThrowsInstanceOf(() => dn.of(), RangeError); + assertThrowsInstanceOf(() => dn.of(null), RangeError); + assertThrowsInstanceOf(() => dn.of(Symbol()), TypeError); + assertThrowsInstanceOf(() => dn.of(0), RangeError); + assertThrowsInstanceOf(() => dn.of(1), RangeError); + + // Throws an error if not one of ["am", "pm"]. + assertThrowsInstanceOf(() => dn.of(""), RangeError); + assertThrowsInstanceOf(() => dn.of("AM"), RangeError); + assertThrowsInstanceOf(() => dn.of("PM"), RangeError); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/DisplayNames/language-dialect.js b/js/src/tests/non262/Intl/DisplayNames/language-dialect.js new file mode 100644 index 0000000000..c2999bd673 --- /dev/null +++ b/js/src/tests/non262/Intl/DisplayNames/language-dialect.js @@ -0,0 +1,104 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')) + +const tests = { + "en": { + long: { + "de": "German", + "de-AT": "Austrian German", + "de-1996": "German (German orthography of 1996)", + "en": "English", + "en-Hant-GB": "British English (Traditional)", + "en-Hans-US": "American English (Simplified)", + "fr": "French", + "nl-BE": "Flemish", + "cr-Cans": "Cree (Unified Canadian Aboriginal Syllabics)", + }, + short: { + "en-Hant-GB": "UK English (Traditional)", + "en-Hans-US": "US English (Simplified)", + "cr-Cans": "Cree (UCAS)", + }, + narrow: {}, + }, + "de": { + long: { + "de": "Deutsch", + "de-AT": "Österreichisches Deutsch", + "de-1996": "Deutsch (Neue deutsche Rechtschreibung)", + "en": "Englisch", + "en-Hant-GB": "Englisch (Traditionell, Vereinigtes Königreich)", + "en-Hans-US": "Englisch (Vereinfacht, Vereinigte Staaten)", + "fr": "Französisch", + "nl-BE": "Flämisch", + }, + short: { + "en-Hant-GB": "Englisch (GB) (Traditionell)", + "en-Hans-US": "Englisch (USA) (Vereinfacht)", + }, + narrow: {}, + }, + "fr": { + long: { + "de": "allemand", + "de-AT": "allemand autrichien", + "de-1996": "allemand (orthographe allemande de 1996)", + "en": "anglais", + "en-Hant-GB": "anglais britannique (traditionnel)", + "en-Hans-US": "anglais américain (simplifié)", + "fr": "français", + "nl-BE": "flamand", + }, + short: { + "en-Hant-GB": "anglais britannique (traditionnel)", + "en-Hans-US": "anglais américain (simplifié)", + }, + narrow: {}, + }, + "zh": { + long: { + "zh": "中文", + "zh-Hant": "繁体中文", + "zh-Hant-CN": "繁体中文(中国)", + "zh-Hans-HK": "简体中文(中国香港特别行政区)", + }, + short: { + "zh-Hans-HK": "简体中文(香港)" + }, + narrow: {}, + }, + "ar": { + long: { + "ar": "العربية", + "ar-SA": "العربية (المملكة العربية السعودية)", + "zh-MO": "الصينية (منطقة ماكاو الإدارية الخاصة)", + }, + short: { + "zh-MO": "الصينية (مكاو)", + }, + narrow: {}, + }, +}; + +for (let [locale, localeTests] of Object.entries(tests)) { + for (let [style, styleTests] of Object.entries(localeTests)) { + let dn = new Intl.DisplayNames(locale, {type: "language", languageDisplay: "dialect", style}); + + let resolved = dn.resolvedOptions(); + assertEq(resolved.locale, locale); + assertEq(resolved.style, style); + assertEq(resolved.type, "language"); + assertEq(resolved.languageDisplay, "dialect"); + assertEq(resolved.fallback, "code"); + + let inheritedTests = {...localeTests.long, ...localeTests.short, ...localeTests.narrow}; + for (let [language, expected] of Object.entries({...inheritedTests, ...styleTests})) { + assertEq(dn.of(language), expected); + + // Also works with objects. + assertEq(dn.of(Object(language)), expected); + } + } +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/DisplayNames/language.js b/js/src/tests/non262/Intl/DisplayNames/language.js new file mode 100644 index 0000000000..48fb72056e --- /dev/null +++ b/js/src/tests/non262/Intl/DisplayNames/language.js @@ -0,0 +1,205 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')) + +const tests = { + "en": { + long: { + "de": "German", + "de-AT": "German (Austria)", + "de-1996": "German (German orthography of 1996)", + "en": "English", + "en-Hant-GB": "English (Traditional, United Kingdom)", + "en-Hans-US": "English (Simplified, United States)", + "fr": "French", + "nl-BE": "Dutch (Belgium)", + "cr-Cans": "Cree (Unified Canadian Aboriginal Syllabics)", + }, + short: { + "en-Hant-GB": "English (Traditional, UK)", + "en-Hans-US": "English (Simplified, US)", + "cr-Cans": "Cree (UCAS)", + }, + narrow: {}, + }, + "de": { + long: { + "de": "Deutsch", + "de-AT": "Deutsch (Österreich)", + "de-1996": "Deutsch (Neue deutsche Rechtschreibung)", + "en": "Englisch", + "en-Hant-GB": "Englisch (Traditionell, Vereinigtes Königreich)", + "en-Hans-US": "Englisch (Vereinfacht, Vereinigte Staaten)", + "fr": "Französisch", + "nl-BE": "Niederländisch (Belgien)", + }, + short: { + "en-Hant-GB": "Englisch (Traditionell, UK)", + "en-Hans-US": "Englisch (Vereinfacht, USA)", + }, + narrow: {}, + }, + "fr": { + long: { + "de": "allemand", + "de-AT": "allemand (Autriche)", + "de-1996": "allemand (orthographe allemande de 1996)", + "en": "anglais", + "en-Hant-GB": "anglais (traditionnel, Royaume-Uni)", + "en-Hans-US": "anglais (simplifié, États-Unis)", + "fr": "français", + "nl-BE": "néerlandais (Belgique)", + }, + short: { + "en-Hant-GB": "anglais (traditionnel, R.-U.)", + "en-Hans-US": "anglais (simplifié, É.-U.)", + }, + narrow: {}, + }, + "zh": { + long: { + "zh": "中文", + "zh-Hant": "中文(繁体)", + "zh-Hant-CN": "中文(繁体,中国)", + "zh-Hans-HK": "中文(简体,中国香港特别行政区)", + }, + short: { + "zh-Hans-HK": "中文(简体,香港)" + }, + narrow: {}, + }, + "ar": { + long: { + "ar": "العربية", + "ar-SA": "العربية (المملكة العربية السعودية)", + "zh-MO": "الصينية (منطقة ماكاو الإدارية الخاصة)", + }, + short: { + "zh-MO": "الصينية (مكاو)", + }, + narrow: {}, + }, +}; + +for (let [locale, localeTests] of Object.entries(tests)) { + for (let [style, styleTests] of Object.entries(localeTests)) { + let dn = new Intl.DisplayNames(locale, {type: "language", languageDisplay: "standard", style}); + + let resolved = dn.resolvedOptions(); + assertEq(resolved.locale, locale); + assertEq(resolved.style, style); + assertEq(resolved.type, "language"); + assertEq(resolved.languageDisplay, "standard"); + assertEq(resolved.fallback, "code"); + + let inheritedTests = {...localeTests.long, ...localeTests.short, ...localeTests.narrow}; + for (let [language, expected] of Object.entries({...inheritedTests, ...styleTests})) { + assertEq(dn.of(language), expected); + + // Also works with objects. + assertEq(dn.of(Object(language)), expected); + } + } +} + +{ + let dn = new Intl.DisplayNames("en", {type: "language"}); + + // Performs ToString on the input and then validates the stringified result. + assertThrowsInstanceOf(() => dn.of(), RangeError); + assertThrowsInstanceOf(() => dn.of(null), RangeError); + assertThrowsInstanceOf(() => dn.of(Symbol()), TypeError); + assertThrowsInstanceOf(() => dn.of(0), RangeError); + + // Throws an error if |code| can't be parsed as a `unicode_language_id` production. + assertThrowsInstanceOf(() => dn.of("en-"), RangeError); + assertThrowsInstanceOf(() => dn.of("en-u-ca-gregory"), RangeError); + assertThrowsInstanceOf(() => dn.of("en-x-private"), RangeError); +} + +// Test fallback behaviour. +{ + let dn1 = new Intl.DisplayNames("en", {type: "language"}); + let dn2 = new Intl.DisplayNames("en", {type: "language", fallback: "code"}); + let dn3 = new Intl.DisplayNames("en", {type: "language", fallback: "none"}); + + assertEq(dn1.resolvedOptions().fallback, "code"); + assertEq(dn2.resolvedOptions().fallback, "code"); + assertEq(dn3.resolvedOptions().fallback, "none"); + + // "aaa" is not a registered language code. + assertEq(dn1.of("aaa"), "aaa"); + assertEq(dn2.of("aaa"), "aaa"); + assertEq(dn3.of("aaa"), undefined); + + // "aaa" is not a registered language code. + assertEq(dn1.of("aaa-Latn"), "aaa-Latn"); + assertEq(dn2.of("aaa-Latn"), "aaa-Latn"); + assertEq(dn3.of("aaa-Latn"), undefined); + + // "Aaaa" is not a registered script code. + assertEq(dn1.of("en-Aaaa"), "en-Aaaa"); + assertEq(dn2.of("en-Aaaa"), "en-Aaaa"); + assertEq(dn3.of("en-Aaaa"), undefined); + + // "AA" is not a registered region code. + assertEq(dn1.of("en-AA"), "en-AA"); + assertEq(dn2.of("en-AA"), "en-AA"); + assertEq(dn3.of("en-AA"), undefined); + + // "XZ" doesn't have any localised names. + assertEq(dn1.of("en-XZ"), "en-XZ"); + assertEq(dn2.of("en-XZ"), "en-XZ"); + assertEq(dn3.of("en-XZ"), undefined); + + // "998" is canonicalised to "XZ". + assertEq(dn1.of("en-998"), "en-XZ"); + assertEq(dn2.of("en-998"), "en-XZ"); + assertEq(dn3.of("en-998"), undefined); + + // The returned fallback is in canonical case. + assertEq(dn1.of("AAA"), "aaa"); + assertEq(dn2.of("AAA"), "aaa"); + assertEq(dn3.of("AAA"), undefined); + + assertEq(dn1.of("En-aaaa"), "en-Aaaa"); + assertEq(dn2.of("En-aaaa"), "en-Aaaa"); + assertEq(dn3.of("En-aaaa"), undefined); + + assertEq(dn1.of("EN-aa"), "en-AA"); + assertEq(dn2.of("EN-aa"), "en-AA"); + assertEq(dn3.of("EN-aa"), undefined); +} + +// Ensure language tag canonicalisation is performed. +{ + let dn = new Intl.DisplayNames("en", {type: "language", fallback: "none"}); + + assertEq(dn.of("ru-RU"), "Russian (Russia)"); + + // ICU's canonicalisation supports "SU" -> "RU". + assertEq(Intl.getCanonicalLocales("ru-SU")[0], "ru-RU"); + assertEq(dn.of("ru-SU"), "Russian (Russia)"); + + // ICU's canonicalisation doesn't support "172" -> "RU". + assertEq(Intl.getCanonicalLocales("ru-172")[0], "ru-RU"); + assertEq(dn.of("ru-172"), "Russian (Russia)"); +} + +// Test when case isn't canonical. +{ + let dn = new Intl.DisplayNames("en", {type: "language", fallback: "none"}); + + assertEq(dn.of("IT-LATN-IT"), "Italian (Latin, Italy)"); + assertEq(dn.of("it-latn-it"), "Italian (Latin, Italy)"); +} + +// resolvedOptions() only outputs "languageDisplay" when the type is "language". +{ + let dn1 = new Intl.DisplayNames("en", {type: "language"}); + let dn2 = new Intl.DisplayNames("en", {type: "script"}); + + assertEq(dn1.resolvedOptions().languageDisplay, "dialect"); + assertEq(dn2.resolvedOptions().hasOwnProperty("languageDisplay"), false); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/DisplayNames/month-calendar.js b/js/src/tests/non262/Intl/DisplayNames/month-calendar.js new file mode 100644 index 0000000000..9a7d9abdaa --- /dev/null +++ b/js/src/tests/non262/Intl/DisplayNames/month-calendar.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')||!this.hasOwnProperty('addIntlExtras')) + +addMozIntlDisplayNames(this); + +let dn1 = new Intl.DisplayNames("en", {type: "month", calendar: "gregory"}); +assertEq(dn1.of(1), "January"); +assertEq(dn1.resolvedOptions().calendar, "gregory"); + +let dn2 = new Intl.DisplayNames("en", {type: "month", calendar: "hebrew"}); +assertEq(dn2.of(1), "Tishri"); +assertEq(dn2.resolvedOptions().calendar, "hebrew"); + +let dn3 = new Intl.DisplayNames("en", {type: "month", calendar: "islamicc"}); +assertEq(dn3.of(1), "Muharram"); +assertEq(dn3.resolvedOptions().calendar, "islamic-civil"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/DisplayNames/month.js b/js/src/tests/non262/Intl/DisplayNames/month.js new file mode 100644 index 0000000000..0bd7a02a80 --- /dev/null +++ b/js/src/tests/non262/Intl/DisplayNames/month.js @@ -0,0 +1,104 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')||!this.hasOwnProperty('addIntlExtras')) + +addMozIntlDisplayNames(this); + +const tests = { + "en": { + long: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", 13], + short: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 13], + narrow: ["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D", 13], + }, + "de": { + long: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember", 13], + short: ["Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez", 13], + narrow: ["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D", 13], + }, + "fr": { + long: ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre", 13], + short: ["janv.", "févr.", "mars", "avr.", "mai", "juin", "juil.", "août", "sept.", "oct.", "nov.", "déc.", 13], + narrow: ["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D", 13], + }, + "zh": { + long: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月", 13], + short: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月", 13], + narrow: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", 13], + }, + "zh-u-ca-chinese": { + long: ["正月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "腊月", 13], + short: ["正月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "腊月", 13], + narrow: ["正", "二", "三", "四", "五", "六", "七", "八", "九", "十", "冬", "腊", 13], + }, + "en-u-ca-hebrew": { + long: ["Tishri", "Heshvan", "Kislev", "Tevet", "Shevat", "Adar I", "Adar", "Nisan", "Iyar", "Sivan", "Tamuz", "Av", "Elul"], + short: ["Tishri", "Heshvan", "Kislev", "Tevet", "Shevat", "Adar I", "Adar", "Nisan", "Iyar", "Sivan", "Tamuz", "Av", "Elul"], + narrow: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13"], + }, +}; + +for (let [locale, localeTests] of Object.entries(tests)) { + let defaultCalendar = new Intl.DateTimeFormat(locale).resolvedOptions().calendar; + + for (let [style, styleTests] of Object.entries(localeTests)) { + let dn = new Intl.DisplayNames(locale, {type: "month", style}); + + let resolved = dn.resolvedOptions(); + assertEq(resolved.locale, locale); + assertEq(resolved.calendar, defaultCalendar); + assertEq(resolved.style, style); + assertEq(resolved.type, "month"); + assertEq(resolved.fallback, "code"); + + for (let i = 0; i < 13; i++) { + assertEq(dn.of(i + 1), String(styleTests[i])); + + // Also works with strings. + assertEq(dn.of(String(i + 1)), String(styleTests[i])); + + // Also works with objects. + assertEq(dn.of(Object(i + 1)), String(styleTests[i])); + } + } +} + +{ + let dn = new Intl.DisplayNames("en", {type: "month"}); + + // Performs ToString on the input and then validates the stringified result. + assertThrowsInstanceOf(() => dn.of(), RangeError); + assertThrowsInstanceOf(() => dn.of(null), RangeError); + assertThrowsInstanceOf(() => dn.of(Symbol()), TypeError); + + // Throws an error if |code| isn't an integer. + assertThrowsInstanceOf(() => dn.of(1.5), RangeError); + assertThrowsInstanceOf(() => dn.of(-Infinity), RangeError); + assertThrowsInstanceOf(() => dn.of(Infinity), RangeError); + assertThrowsInstanceOf(() => dn.of(NaN), RangeError); + + // Throws an error if outside of [1, 13]. + assertThrowsInstanceOf(() => dn.of(-1), RangeError); + assertThrowsInstanceOf(() => dn.of(0), RangeError); + assertThrowsInstanceOf(() => dn.of(14), RangeError); +} + +// Test fallback behaviour. +{ + let dn1 = new Intl.DisplayNames("en", {type: "month"}); + let dn2 = new Intl.DisplayNames("en", {type: "month", fallback: "code"}); + let dn3 = new Intl.DisplayNames("en", {type: "month", fallback: "none"}); + + assertEq(dn1.resolvedOptions().fallback, "code"); + assertEq(dn2.resolvedOptions().fallback, "code"); + assertEq(dn3.resolvedOptions().fallback, "none"); + + assertEq(dn1.resolvedOptions().calendar, "gregory"); + assertEq(dn2.resolvedOptions().calendar, "gregory"); + assertEq(dn3.resolvedOptions().calendar, "gregory"); + + // The Gregorian calendar doesn't have a thirteenth month. + assertEq(dn1.of("13"), "13"); + assertEq(dn2.of("13"), "13"); + assertEq(dn3.of("13"), undefined); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/DisplayNames/quarter.js b/js/src/tests/non262/Intl/DisplayNames/quarter.js new file mode 100644 index 0000000000..f74b3b439a --- /dev/null +++ b/js/src/tests/non262/Intl/DisplayNames/quarter.js @@ -0,0 +1,74 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')||!this.hasOwnProperty('addIntlExtras')) + +addMozIntlDisplayNames(this); + +const tests = { + "en": { + long: ["1st quarter", "2nd quarter", "3rd quarter", "4th quarter"], + short: ["Q1", "Q2", "Q3", "Q4"], + narrow: ["1", "2", "3", "4"], + }, + "de": { + long: ["1. Quartal", "2. Quartal", "3. Quartal", "4. Quartal"], + short: ["Q1", "Q2", "Q3", "Q4"], + narrow: ["1", "2", "3", "4"], + }, + "fr": { + long: ["1er trimestre", "2e trimestre", "3e trimestre", "4e trimestre"], + short: ["T1", "T2", "T3", "T4"], + narrow: ["1", "2", "3", "4"], + }, + "zh": { + long: ["第一季度", "第二季度", "第三季度", "第四季度"], + short: ["1季度", "2季度", "3季度", "4季度"], + narrow: ["1", "2", "3", "4"], + }, +}; + +for (let [locale, localeTests] of Object.entries(tests)) { + let defaultCalendar = new Intl.DateTimeFormat(locale).resolvedOptions().calendar; + + for (let [style, styleTests] of Object.entries(localeTests)) { + let dn = new Intl.DisplayNames(locale, {type: "quarter", style}); + + let resolved = dn.resolvedOptions(); + assertEq(resolved.locale, locale); + assertEq(resolved.calendar, defaultCalendar); + assertEq(resolved.style, style); + assertEq(resolved.type, "quarter"); + assertEq(resolved.fallback, "code"); + + for (let i = 0; i < 4; i++) { + assertEq(dn.of(i + 1), styleTests[i]); + + // Also works with strings. + assertEq(dn.of(String(i + 1)), styleTests[i]); + + // Also works with objects. + assertEq(dn.of(Object(i + 1)), styleTests[i]); + } + } +} + +{ + let dn = new Intl.DisplayNames("en", {type: "quarter"}); + + // Performs ToString on the input and then validates the stringified result. + assertThrowsInstanceOf(() => dn.of(), RangeError); + assertThrowsInstanceOf(() => dn.of(null), RangeError); + assertThrowsInstanceOf(() => dn.of(Symbol()), TypeError); + + // Throws an error if |code| isn't an integer. + assertThrowsInstanceOf(() => dn.of(1.5), RangeError); + assertThrowsInstanceOf(() => dn.of(-Infinity), RangeError); + assertThrowsInstanceOf(() => dn.of(Infinity), RangeError); + assertThrowsInstanceOf(() => dn.of(NaN), RangeError); + + // Throws an error if outside of [1, 4]. + assertThrowsInstanceOf(() => dn.of(-1), RangeError); + assertThrowsInstanceOf(() => dn.of(0), RangeError); + assertThrowsInstanceOf(() => dn.of(5), RangeError); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/DisplayNames/region.js b/js/src/tests/non262/Intl/DisplayNames/region.js new file mode 100644 index 0000000000..2d1bfe58d8 --- /dev/null +++ b/js/src/tests/non262/Intl/DisplayNames/region.js @@ -0,0 +1,157 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')) + +const tests = { + "en": { + long: { + "DE": "Germany", + "GB": "United Kingdom", + "US": "United States", + "FR": "France", + }, + short: { + "GB": "UK", + "US": "US", + }, + narrow: {}, + }, + "de": { + long: { + "DE": "Deutschland", + "GB": "Vereinigtes Königreich", + "US": "Vereinigte Staaten", + "FR": "Frankreich", + }, + short: { + "GB": "UK", + "US": "USA", + }, + narrow: {}, + }, + "fr": { + long: { + "DE": "Allemagne", + "GB": "Royaume-Uni", + "US": "États-Unis", + "FR": "France", + }, + short: { + "GB": "R.-U.", + "US": "É.-U.", + }, + narrow: {}, + }, + "zh": { + long: { + "CN": "中国", + "HK": "中国香港特别行政区", + }, + short: { + "HK": "香港" + }, + narrow: {}, + }, + "ar": { + long: { + "SA": "المملكة العربية السعودية", + "MO": "منطقة ماكاو الإدارية الخاصة", + }, + short: { + "MO": "مكاو", + }, + narrow: {}, + }, +}; + +for (let [locale, localeTests] of Object.entries(tests)) { + for (let [style, styleTests] of Object.entries(localeTests)) { + let dn = new Intl.DisplayNames(locale, {type: "region", style}); + + let resolved = dn.resolvedOptions(); + assertEq(resolved.locale, locale); + assertEq(resolved.style, style); + assertEq(resolved.type, "region"); + assertEq(resolved.fallback, "code"); + + let inheritedTests = {...localeTests.long, ...localeTests.short, ...localeTests.narrow}; + for (let [region, expected] of Object.entries({...inheritedTests, ...styleTests})) { + assertEq(dn.of(region), expected); + + // Also works with objects. + assertEq(dn.of(Object(region)), expected); + } + } +} + +{ + let dn = new Intl.DisplayNames("en", {type: "region"}); + + // Performs ToString on the input and then validates the stringified result. + assertThrowsInstanceOf(() => dn.of(), RangeError); + assertThrowsInstanceOf(() => dn.of(null), RangeError); + assertThrowsInstanceOf(() => dn.of(Symbol()), TypeError); + assertThrowsInstanceOf(() => dn.of(0), RangeError); + + // Throws an error if |code| can't be parsed as a `unicode_region_subtag` production. + assertThrowsInstanceOf(() => dn.of("CA-"), RangeError); + assertThrowsInstanceOf(() => dn.of("en-CA"), RangeError); +} + +// Test fallback behaviour. +{ + let dn1 = new Intl.DisplayNames("en", {type: "region"}); + let dn2 = new Intl.DisplayNames("en", {type: "region", fallback: "code"}); + let dn3 = new Intl.DisplayNames("en", {type: "region", fallback: "none"}); + + assertEq(dn1.resolvedOptions().fallback, "code"); + assertEq(dn2.resolvedOptions().fallback, "code"); + assertEq(dn3.resolvedOptions().fallback, "none"); + + // "AA" is not a registered region code. + assertEq(dn1.of("AA"), "AA"); + assertEq(dn2.of("AA"), "AA"); + assertEq(dn3.of("AA"), undefined); + + // The returned fallback is in canonical case. + assertEq(dn1.of("aa"), "AA"); + assertEq(dn2.of("aa"), "AA"); + assertEq(dn3.of("aa"), undefined); + + // "998" is canonicalised to "XZ", but "XZ" has no localised names. + assertEq(new Intl.Locale("und-998").region, "XZ"); + + // Ensure we return the input and not the canonicalised input. + assertEq(dn1.of("998"), "998"); + assertEq(dn2.of("998"), "998"); + assertEq(dn3.of("998"), undefined); + + // "XZ" should be consistent with "998". + assertEq(dn1.of("XZ"), "XZ"); + assertEq(dn2.of("XZ"), "XZ"); + assertEq(dn3.of("XZ"), undefined); +} + +// Ensure language tag canonicalisation is performed. +{ + let dn = new Intl.DisplayNames("en", {type: "region", fallback: "none"}); + + assertEq(dn.of("RU"), "Russia"); + + // ICU's canonicalisation supports "SU" -> "RU". + assertEq(Intl.getCanonicalLocales("ru-SU")[0], "ru-RU"); + assertEq(dn.of("SU"), "Russia"); + + // ICU's canonicalisation doesn't support "172" -> "RU". + assertEq(Intl.getCanonicalLocales("ru-172")[0], "ru-RU"); + assertEq(dn.of("172"), "Russia"); +} + +// Test when case isn't canonical. +{ + let dn = new Intl.DisplayNames("en", {type: "region", fallback: "none"}); + + assertEq(dn.of("IT"), "Italy"); + assertEq(dn.of("it"), "Italy"); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/DisplayNames/script.js b/js/src/tests/non262/Intl/DisplayNames/script.js new file mode 100644 index 0000000000..43b3ad5308 --- /dev/null +++ b/js/src/tests/non262/Intl/DisplayNames/script.js @@ -0,0 +1,134 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')) + +const tests = { + "en": { + long: { + "Latn": "Latin", + "Hant": "Traditional Han", + "Hans": "Simplified Han", + "Cans": "Unified Canadian Aboriginal Syllabics", + }, + short: { + "Hant": "Traditional", + "Hans": "Simplified", + "Cans": "UCAS", + }, + narrow: {}, + }, + "de": { + long: { + "Latn": "Lateinisch", + "Hant": "Traditionelles Chinesisch", + "Hans": "Vereinfachtes Chinesisch", + }, + short: { + "Hant": "Traditionell", + "Hans": "Vereinfacht", + }, + narrow: {}, + }, + "fr": { + long: { + "Latn": "latin", + "Hant": "sinogrammes traditionnels", + "Hans": "sinogrammes simplifiés", + }, + short: { + "Hant": "traditionnel", + "Hans": "simplifié", + }, + narrow: {}, + }, + "zh": { + long: { + "Latn": "拉丁文", + "Hant": "繁体中文", + "Hans": "简体中文", + }, + short: { + "Hant": "繁体", + "Hans": "简体", + }, + narrow: {}, + }, + "ar": { + long: { + "Latn": "اللاتينية", + "Arab": "العربية", + "Hant": "الهان التقليدية", + "Hans": "الهان المبسطة", + }, + short: { + "Hant": "التقليدية", + "Hans": "المبسطة", + }, + narrow: {}, + }, +}; + +for (let [locale, localeTests] of Object.entries(tests)) { + for (let [style, styleTests] of Object.entries(localeTests)) { + let dn = new Intl.DisplayNames(locale, {type: "script", style}); + + let resolved = dn.resolvedOptions(); + assertEq(resolved.locale, locale); + assertEq(resolved.style, style); + assertEq(resolved.type, "script"); + assertEq(resolved.fallback, "code"); + + let inheritedTests = {...localeTests.long, ...localeTests.short, ...localeTests.narrow}; + for (let [script, expected] of Object.entries({...inheritedTests, ...styleTests})) { + assertEq(dn.of(script), expected); + + // Also works with objects. + assertEq(dn.of(Object(script)), expected); + } + } +} + +{ + let dn = new Intl.DisplayNames("en", {type: "script"}); + + // Performs ToString on the input and then validates the stringified result. + assertThrowsInstanceOf(() => dn.of(), RangeError); + assertThrowsInstanceOf(() => dn.of(Symbol()), TypeError); + assertThrowsInstanceOf(() => dn.of(0), RangeError); + + // ToString(null) = "null", which passes `unicode_script_subtag`. + dn.of(null); // no error + + // Throws an error if |code| can't be parsed as a `unicode_script_subtag` production. + assertThrowsInstanceOf(() => dn.of("latn-"), RangeError); + assertThrowsInstanceOf(() => dn.of("en-latn"), RangeError); +} + +// Test fallback behaviour. +{ + let dn1 = new Intl.DisplayNames("en", {type: "script"}); + let dn2 = new Intl.DisplayNames("en", {type: "script", fallback: "code"}); + let dn3 = new Intl.DisplayNames("en", {type: "script", fallback: "none"}); + + assertEq(dn1.resolvedOptions().fallback, "code"); + assertEq(dn2.resolvedOptions().fallback, "code"); + assertEq(dn3.resolvedOptions().fallback, "none"); + + // "Aaaa" is not a registered script code. + assertEq(dn1.of("Aaaa"), "Aaaa"); + assertEq(dn2.of("Aaaa"), "Aaaa"); + assertEq(dn3.of("Aaaa"), undefined); + + // The returned fallback is in canonical case. + assertEq(dn1.of("aaaa"), "Aaaa"); + assertEq(dn2.of("aaaa"), "Aaaa"); + assertEq(dn3.of("aaaa"), undefined); +} + +// Test when case isn't canonical. +{ + let dn = new Intl.DisplayNames("en", {type: "script", fallback: "none"}); + + assertEq(dn.of("LATN"), "Latin"); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/DisplayNames/shell.js b/js/src/tests/non262/Intl/DisplayNames/shell.js new file mode 100644 index 0000000000..20326b0254 --- /dev/null +++ b/js/src/tests/non262/Intl/DisplayNames/shell.js @@ -0,0 +1,6 @@ +// Add |Intl.MozDisplayNames| to the Intl object. +function addMozIntlDisplayNames(global) { + let obj = {}; + global.addIntlExtras(obj); + global.Intl.DisplayNames = obj.DisplayNames; +} diff --git a/js/src/tests/non262/Intl/DisplayNames/weekday.js b/js/src/tests/non262/Intl/DisplayNames/weekday.js new file mode 100644 index 0000000000..fd19f24bb1 --- /dev/null +++ b/js/src/tests/non262/Intl/DisplayNames/weekday.js @@ -0,0 +1,77 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')||!this.hasOwnProperty('addIntlExtras')) + +addMozIntlDisplayNames(this); + +const tests = { + "en": { + long: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], + // short: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], + short: ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"], + narrow: ["M", "T", "W", "T", "F", "S", "S"], + }, + "de": { + long: ["Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag"], + // short: ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"], + short: ["Mo.", "Di.", "Mi.", "Do.", "Fr.", "Sa.", "So."], + narrow: ["M", "D", "M", "D", "F", "S", "S"], + }, + "fr": { + long: ["lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche"], + // short: ["lun.", "mar.", "mer.", "jeu.", "ven.", "sam.", "dim."], + short: ["lu", "ma", "me", "je", "ve", "sa", "di"], + narrow: ["L", "M", "M", "J", "V", "S", "D"], + }, + "zh": { + long: ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"], + short: ["周一", "周二", "周三", "周四", "周五", "周六", "周日"], + narrow: ["一", "二", "三", "四", "五", "六", "日"], + }, +}; + +for (let [locale, localeTests] of Object.entries(tests)) { + let defaultCalendar = new Intl.DateTimeFormat(locale).resolvedOptions().calendar; + + for (let [style, styleTests] of Object.entries(localeTests)) { + let dn = new Intl.DisplayNames(locale, {type: "weekday", style}); + + let resolved = dn.resolvedOptions(); + assertEq(resolved.locale, locale); + assertEq(resolved.calendar, defaultCalendar); + assertEq(resolved.style, style); + assertEq(resolved.type, "weekday"); + assertEq(resolved.fallback, "code"); + + for (let i = 0; i < 7; i++) { + assertEq(dn.of(i + 1), styleTests[i]); + + // Also works with strings. + assertEq(dn.of(String(i + 1)), styleTests[i]); + + // Also works with objects. + assertEq(dn.of(Object(i + 1)), styleTests[i]); + } + } +} + +{ + let dn = new Intl.DisplayNames("en", {type: "weekday"}); + + // Performs ToString on the input and then validates the stringified result. + assertThrowsInstanceOf(() => dn.of(), RangeError); + assertThrowsInstanceOf(() => dn.of(null), RangeError); + assertThrowsInstanceOf(() => dn.of(Symbol()), TypeError); + + // Throws an error if |code| isn't an integer. + assertThrowsInstanceOf(() => dn.of(1.5), RangeError); + assertThrowsInstanceOf(() => dn.of(-Infinity), RangeError); + assertThrowsInstanceOf(() => dn.of(Infinity), RangeError); + assertThrowsInstanceOf(() => dn.of(NaN), RangeError); + + // Throws an error if outside of [1, 7]. + assertThrowsInstanceOf(() => dn.of(-1), RangeError); + assertThrowsInstanceOf(() => dn.of(0), RangeError); + assertThrowsInstanceOf(() => dn.of(8), RangeError); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/ListFormat/browser.js b/js/src/tests/non262/Intl/ListFormat/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Intl/ListFormat/conjunction-type.js b/js/src/tests/non262/Intl/ListFormat/conjunction-type.js new file mode 100644 index 0000000000..320a235271 --- /dev/null +++ b/js/src/tests/non262/Intl/ListFormat/conjunction-type.js @@ -0,0 +1,116 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')) + +// Note: Use the same test locales as used in unit-type.js + +const {Element, Literal} = ListFormatParts; +const styles = ["long", "short", "narrow"]; + +// Test with zero elements. +{ + const list = []; + const expected = []; + const locales = ["ar", "de", "en", "es", "ja", "nl", "th", "zh"]; + + for (let locale of locales) { + for (let style of styles) { + let lf = new Intl.ListFormat(locale, {type: "conjunction", style}); + assertParts(lf, list, expected); + } + } +} + +// Test with one element. +{ + const list = ["A"]; + const expected = [Element(list[0])]; + const locales = ["ar", "de", "en", "es", "ja", "nl", "th", "zh"]; + + for (let locale of locales) { + for (let style of styles) { + let lf = new Intl.ListFormat(locale, {type: "conjunction", style}); + assertParts(lf, list, expected); + } + } +} + +// Test with two elements to cover the [[Template2]] case. +{ + const list = ["A", "B"]; + + const testData = { + "ar": { long: [Element("A"), Literal(" و"), Element("B")] }, + "de": { long: [Element("A"), Literal(" und "), Element("B")] }, + "en": { + long: [Element("A"), Literal(" and "), Element("B")], + short: [Element("A"), Literal(" & "), Element("B")], + narrow: [Element("A"), Literal(", "), Element("B")], + }, + "es": { long: [Element("A"), Literal(" y "), Element("B")] }, + "ja": { long: [Element("A"), Literal("、"), Element("B")] }, + "nl": { long: [Element("A"), Literal(" en "), Element("B")] }, + "th": { long: [Element("A"), Literal("และ"), Element("B")] }, + "zh": { + long: [Element("A"), Literal("和"), Element("B")], + narrow: [Element("A"), Literal("、"), Element("B")], + }, + }; + + for (let [locale, localeData] of Object.entries(testData)) { + for (let style of styles) { + let lf = new Intl.ListFormat(locale, {type: "conjunction", style}); + let {[style]: expected = localeData.long} = localeData; + assertParts(lf, list, expected); + } + } +} + +// Test with more than two elements. +// +// Use four elements to cover all template parts ([[TemplateStart]], [[TemplateMiddle]], and +// [[TemplateEnd]]). +{ + const list = ["A", "B", "C", "D"]; + + const testData = { + "ar": { + long: [Element("A"), Literal(" و"), Element("B"), Literal(" و"), Element("C"), Literal(" و"), Element("D")], + short: [Element("A"), Literal(" و"), Element("B"), Literal(" و"), Element("C"), Literal(" و"), Element("D")], + narrow: [Element("A"), Literal(" و"), Element("B"), Literal(" و"), Element("C"), Literal(" و"), Element("D")], + }, + "de": { + long: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(" und "), Element("D")], + }, + "en": { + long: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(", and "), Element("D")], + short: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(", & "), Element("D")], + narrow: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(", "), Element("D")], + }, + "es": { + long: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(" y "), Element("D")], + }, + "ja": { + long: [Element("A"), Literal("、"), Element("B"), Literal("、"), Element("C"), Literal("、"), Element("D")], + }, + "nl": { + long: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(" en "), Element("D")], + }, + "th": { + long: [Element("A"), Literal(" "), Element("B"), Literal(" "), Element("C"), Literal(" และ"), Element("D")], + }, + "zh": { + long: [Element("A"), Literal("、"), Element("B"), Literal("、"), Element("C"), Literal("和"), Element("D")], + narrow: [Element("A"), Literal("、"), Element("B"), Literal("、"), Element("C"), Literal("、"), Element("D")], + }, + }; + + for (let [locale, localeData] of Object.entries(testData)) { + for (let style of styles) { + let lf = new Intl.ListFormat(locale, {type: "conjunction", style}); + let {[style]: expected = localeData.long} = localeData; + assertParts(lf, list, expected); + } + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/ListFormat/cross-compartment.js b/js/src/tests/non262/Intl/ListFormat/cross-compartment.js new file mode 100644 index 0000000000..37c45ef75c --- /dev/null +++ b/js/src/tests/non262/Intl/ListFormat/cross-compartment.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')) + +var g = newGlobal(); + +var locale = "en"; +var list = ["a", "b", "c"]; + +var listFormat = new Intl.ListFormat(locale); +var ccwListFormat = new g.Intl.ListFormat(locale); + +// Intl.ListFormat.prototype.format +{ + var fn = Intl.ListFormat.prototype.format; + + var expectedValue = fn.call(listFormat, list); + var actualValue = fn.call(ccwListFormat, list); + + assertEq(actualValue, expectedValue); +} + +// Intl.ListFormat.prototype.formatToParts +{ + var fn = Intl.ListFormat.prototype.formatToParts; + + var expectedValue = fn.call(listFormat, list); + var actualValue = fn.call(ccwListFormat, list); + + assertDeepEq(actualValue, expectedValue); +} + +// Intl.ListFormat.prototype.resolvedOptions +{ + var fn = Intl.ListFormat.prototype.resolvedOptions; + + var expectedValue = fn.call(listFormat); + var actualValue = fn.call(ccwListFormat); + + assertDeepEq(actualValue, expectedValue); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/ListFormat/disjunction-type.js b/js/src/tests/non262/Intl/ListFormat/disjunction-type.js new file mode 100644 index 0000000000..2713a8ae07 --- /dev/null +++ b/js/src/tests/non262/Intl/ListFormat/disjunction-type.js @@ -0,0 +1,108 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')) + +// Note: Use the same test locales as used in unit-type.js + +const {Element, Literal} = ListFormatParts; +const styles = ["long", "short", "narrow"]; + +// Test with zero elements. +{ + const list = []; + const expected = []; + const locales = ["ar", "de", "en", "es", "ja", "nl", "th", "zh"]; + + for (let locale of locales) { + for (let style of styles) { + let lf = new Intl.ListFormat(locale, {type: "disjunction", style}); + assertParts(lf, list, expected); + } + } +} + +// Test with one element. +{ + const list = ["A"]; + const expected = [Element(list[0])]; + const locales = ["ar", "de", "en", "es", "ja", "nl", "th", "zh"]; + + for (let locale of locales) { + for (let style of styles) { + let lf = new Intl.ListFormat(locale, {type: "disjunction", style}); + assertParts(lf, list, expected); + } + } +} + +// Test with two elements to cover the [[Template2]] case. +{ + const list = ["A", "B"]; + + const testData = { + "ar": { long: [Element("A"), Literal(" أو "), Element("B")] }, + "de": { long: [Element("A"), Literal(" oder "), Element("B")] }, + "en": { long: [Element("A"), Literal(" or "), Element("B")] }, + "es": { long: [Element("A"), Literal(" o "), Element("B")] }, + "ja": { long: [Element("A"), Literal("または"), Element("B")] }, + "nl": { long: [Element("A"), Literal(" of "), Element("B")] }, + "th": { + long: [Element("A"), Literal(" หรือ "), Element("B")], + short: [Element("A"), Literal("หรือ"), Element("B")], + narrow: [Element("A"), Literal("หรือ"), Element("B")], + }, + "zh": { long: [Element("A"), Literal("或"), Element("B")] }, + }; + + for (let [locale, localeData] of Object.entries(testData)) { + for (let style of styles) { + let lf = new Intl.ListFormat(locale, {type: "disjunction", style}); + let {[style]: expected = localeData.long} = localeData; + assertParts(lf, list, expected); + } + } +} + +// Test with more than two elements. +// +// Use four elements to cover all template parts ([[TemplateStart]], [[TemplateMiddle]], and +// [[TemplateEnd]]). +{ + const list = ["A", "B", "C", "D"]; + + const testData = { + "ar": { + long: [Element("A"), Literal(" أو "), Element("B"), Literal(" أو "), Element("C"), Literal(" أو "), Element("D")], + }, + "de": { + long: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(" oder "), Element("D")], + }, + "en": { + long: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(", or "), Element("D")], + }, + "es": { + long: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(" o "), Element("D")], + }, + "ja": { + long: [Element("A"), Literal("、"), Element("B"), Literal("、"), Element("C"), Literal("、または"), Element("D")], + }, + "nl": { + long: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(" of "), Element("D")], + }, + "th": { + long: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(" หรือ "), Element("D")], + }, + "zh": { + long: [Element("A"), Literal("、"), Element("B"), Literal("、"), Element("C"), Literal("或"), Element("D")], + }, + }; + + for (let [locale, localeData] of Object.entries(testData)) { + for (let style of styles) { + let lf = new Intl.ListFormat(locale, {type: "disjunction", style}); + let {[style]: expected = localeData.long} = localeData; + assertParts(lf, list, expected); + } + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/ListFormat/same-compartment.js b/js/src/tests/non262/Intl/ListFormat/same-compartment.js new file mode 100644 index 0000000000..a51a041a08 --- /dev/null +++ b/js/src/tests/non262/Intl/ListFormat/same-compartment.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')||!this.wrapWithProto) + +var locale = "en"; +var list = ["a", "b", "c"]; + +var listFormat = new Intl.ListFormat(locale); +var scwListFormat = wrapWithProto(listFormat, Intl.ListFormat.prototype); + +// Intl.ListFormat.prototype.format +{ + var fn = Intl.ListFormat.prototype.format; + + var expectedValue = fn.call(listFormat, list); + var actualValue = fn.call(scwListFormat, list); + + assertEq(actualValue, expectedValue); +} + +// Intl.ListFormat.prototype.formatToParts +{ + var fn = Intl.ListFormat.prototype.formatToParts; + + var expectedValue = fn.call(listFormat, list); + var actualValue = fn.call(scwListFormat, list); + + assertDeepEq(actualValue, expectedValue); +} + +// Intl.ListFormat.prototype.resolvedOptions +{ + var fn = Intl.ListFormat.prototype.resolvedOptions; + + var expectedValue = fn.call(listFormat); + var actualValue = fn.call(scwListFormat); + + assertDeepEq(actualValue, expectedValue); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/ListFormat/shell.js b/js/src/tests/non262/Intl/ListFormat/shell.js new file mode 100644 index 0000000000..70056a579e --- /dev/null +++ b/js/src/tests/non262/Intl/ListFormat/shell.js @@ -0,0 +1,21 @@ +function GenericPartCreator(type) { + return str => ({ type, value: str }); +} + +const ListFormatParts = { + Element: GenericPartCreator("element"), + Literal: GenericPartCreator("literal"), +}; + +function assertParts(lf, x, expected) { + var parts = lf.formatToParts(x); + assertEq(parts.map(part => part.value).join(""), lf.format(x), + "formatToParts and format must agree"); + + var len = parts.length; + assertEq(len, expected.length, "parts count mismatch"); + for (var i = 0; i < len; i++) { + assertEq(parts[i].type, expected[i].type, "type mismatch at " + i); + assertEq(parts[i].value, expected[i].value, "value mismatch at " + i); + } +} diff --git a/js/src/tests/non262/Intl/ListFormat/supported-locales.js b/js/src/tests/non262/Intl/ListFormat/supported-locales.js new file mode 100644 index 0000000000..f5d05e2da5 --- /dev/null +++ b/js/src/tests/non262/Intl/ListFormat/supported-locales.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')) + +// Intl.ListFormat.supportedLocalesOf returns an empty array for unsupported locales. +assertEq(Intl.ListFormat.supportedLocalesOf("art-lobjan").length, 0); + +// And a non-empty array for supported locales. +assertEq(Intl.ListFormat.supportedLocalesOf("en").length, 1); +assertEq(Intl.ListFormat.supportedLocalesOf("en")[0], "en"); + +// If the locale is supported per |Intl.ListFormat.supportedLocalesOf|, the resolved locale +// should reflect this. +for (let locale of Intl.ListFormat.supportedLocalesOf(["en", "de", "th", "ar"])) { + let lf = new Intl.ListFormat(locale); + assertEq(lf.resolvedOptions().locale, locale); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/ListFormat/unit-type.js b/js/src/tests/non262/Intl/ListFormat/unit-type.js new file mode 100644 index 0000000000..8c76677865 --- /dev/null +++ b/js/src/tests/non262/Intl/ListFormat/unit-type.js @@ -0,0 +1,149 @@ +// |reftest| skip -- "unit" type currently not supported + +const {Element, Literal} = ListFormatParts; +const styles = ["long", "short", "narrow"]; + +// Test with zero elements. +{ + const list = []; + const expected = []; + const locales = ["ar", "de", "en", "es", "ja", "nl", "th", "zh"]; + + for (let locale of locales) { + for (let style of styles) { + let lf = new Intl.ListFormat(locale, {type: "unit", style}); + assertParts(lf, list, expected); + } + } +} + +// Test with one element. +{ + const list = ["A"]; + const expected = [Element(list[0])]; + const locales = ["ar", "de", "en", "es", "ja", "nl", "th", "zh"]; + + for (let locale of locales) { + for (let style of styles) { + let lf = new Intl.ListFormat(locale, {type: "unit", style}); + assertParts(lf, list, expected); + } + } +} + +// Test with two elements to cover the [[Template2]] case. +{ + const list = ["A", "B"]; + + const testData = { + "ar": { + long: [Element("A"), Literal(" و"), Element("B")], + narrow: [Element("A"), Literal("، "), Element("B")], + }, + "de": { + long: [Element("A"), Literal(", "), Element("B")], + }, + "en": { + long: [Element("A"), Literal(", "), Element("B")], + narrow: [Element("A"), Literal(" "), Element("B")], + }, + "es": { + long: [Element("A"), Literal(" y "), Element("B")], + narrow: [Element("A"), Literal(" "), Element("B")], + }, + "ja": { + long: [Element("A"), Literal(" "), Element("B")], + narrow: [Element("A"), Element("B")], + }, + "nl": { + long: [Element("A"), Literal(" en "), Element("B")], + short: [Element("A"), Literal(", "), Element("B")], + narrow: [Element("A"), Literal(", "), Element("B")], + }, + "th": { + long: [Element("A"), Literal(" และ "), Element("B")], + short: [Element("A"), Literal(" "), Element("B")], + narrow: [Element("A"), Literal(" "), Element("B")], + }, + "zh": { + long: [Element("A"), Element("B")], + }, + }; + + for (let [locale, localeData] of Object.entries(testData)) { + for (let style of styles) { + let lf = new Intl.ListFormat(locale, {type: "unit", style}); + let {[style]: expected = localeData.long} = localeData; + assertParts(lf, list, expected); + } + } +} + +// Test with more than two elements. +// +// Use four elements to cover all template parts ([[TemplateStart]], [[TemplateMiddle]], and +// [[TemplateEnd]]). +{ + const list = ["A", "B", "C", "D"]; + + const testData = { + // non-ASCII case + "ar": { + long: [Element("A"), Literal("، و"), Element("B"), Literal("، و"), Element("C"), Literal("، و"), Element("D")], + narrow: [Element("A"), Literal("، "), Element("B"), Literal("، "), Element("C"), Literal("، "), Element("D")], + }, + + // all values are equal + "de": { + long: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(" und "), Element("D")], + }, + + // long and short values are equal + "en": { + long: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(", "), Element("D")], + narrow: [Element("A"), Literal(" "), Element("B"), Literal(" "), Element("C"), Literal(" "), Element("D")], + }, + + // all values are different + "es": { + long: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(" y "), Element("D")], + short: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(", "), Element("D")], + narrow: [Element("A"), Literal(" "), Element("B"), Literal(" "), Element("C"), Literal(" "), Element("D")], + }, + + // no spacing for narrow case + "ja": { + long: [Element("A"), Literal(" "), Element("B"), Literal(" "), Element("C"), Literal(" "), Element("D")], + narrow: [Element("A"), Element("B"), Element("C"), Element("D")], + }, + + // short and narrow values are equal + "nl": { + long: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(" en "), Element("D")], + short: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(", "), Element("D")], + narrow: [Element("A"), Literal(", "), Element("B"), Literal(", "), Element("C"), Literal(", "), Element("D")], + }, + + // another non-ASCII case + "th": { + long: [Element("A"), Literal(" "), Element("B"), Literal(" "), Element("C"), Literal(" และ "), Element("D")], + narrow: [Element("A"), Literal(" "), Element("B"), Literal(" "), Element("C"), Literal(" "), Element("D")], + }, + + // no whitespace at all + "zh": { + long: [Element("A"), Element("B"), Element("C"), Element("D")], + }, + }; + + for (let [locale, localeData] of Object.entries(testData)) { + for (let style of styles) { + let lf = new Intl.ListFormat(locale, {type: "unit", style}); + let {[style]: expected = localeData.long} = localeData; + assertParts(lf, list, expected); + } + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/Locale/apply-options-to-tag-canonicalize-twice.js b/js/src/tests/non262/Intl/Locale/apply-options-to-tag-canonicalize-twice.js new file mode 100644 index 0000000000..2a96200757 --- /dev/null +++ b/js/src/tests/non262/Intl/Locale/apply-options-to-tag-canonicalize-twice.js @@ -0,0 +1,11 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')) + +// ApplyOptionsToTag canonicalises the locale identifier before applying the +// options. That means "und-Armn-SU" is first canonicalised to "und-Armn-AM", +// then the language is changed to "ru". If "ru" were applied first, the result +// would be "ru-Armn-RU" instead. +assertEq(new Intl.Locale("und-Armn-SU", {language:"ru"}).toString(), + "ru-Armn-AM"); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/Locale/browser.js b/js/src/tests/non262/Intl/Locale/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Intl/Locale/coerce-options-before-validating-tag.js b/js/src/tests/non262/Intl/Locale/coerce-options-before-validating-tag.js new file mode 100644 index 0000000000..7f57a61132 --- /dev/null +++ b/js/src/tests/non262/Intl/Locale/coerce-options-before-validating-tag.js @@ -0,0 +1,10 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')) + +// Throw a TypeError when the |options| argument is null before validating the +// language tag argument. +assertThrowsInstanceOf(() => { + new Intl.Locale("invalid_tag", null); +}, TypeError); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/Locale/cross-compartment.js b/js/src/tests/non262/Intl/Locale/cross-compartment.js new file mode 100644 index 0000000000..d3788e3eb7 --- /dev/null +++ b/js/src/tests/non262/Intl/Locale/cross-compartment.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')) + +var g = newGlobal(); + +var tag = "de-Latn-AT-u-ca-gregory-nu-latn-co-phonebk-kf-false-kn-hc-h23"; +var locale = new Intl.Locale(tag); +var ccwLocale = new g.Intl.Locale(tag); + +for (var [key, {get, value = get}] of Object.entries(Object.getOwnPropertyDescriptors(Intl.Locale.prototype))) { + if (typeof value === "function") { + if (key !== "constructor") { + var expectedValue = value.call(locale); + + if (typeof expectedValue === "string" || typeof expectedValue === "boolean") { + assertEq(value.call(ccwLocale), expectedValue, key); + } else if (expectedValue instanceof Intl.Locale) { + assertEq(value.call(ccwLocale).toString(), expectedValue.toString(), key); + } else { + throw new Error("unexpected result value"); + } + } else { + assertEq(new value(ccwLocale).toString(), new value(locale).toString(), key); + } + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/Locale/legacy.js b/js/src/tests/non262/Intl/Locale/legacy.js new file mode 100644 index 0000000000..835e886122 --- /dev/null +++ b/js/src/tests/non262/Intl/Locale/legacy.js @@ -0,0 +1,75 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')) + +var testData = [ + { + tag: "cel-gaulish", + options: { + numberingSystem: "latn", + }, + canonical: "xtg-u-nu-latn", + extensions: { + numberingSystem: "latn", + }, + }, + + { + tag: "cel-gaulish", + options: { + region: "FR", + numberingSystem: "latn", + }, + canonical: "xtg-FR-u-nu-latn", + extensions: { + numberingSystem: "latn", + }, + }, + + { + tag: "art-lojban", + options: { + numberingSystem: "latn", + }, + canonical: "jbo-u-nu-latn", + extensions: { + numberingSystem: "latn", + }, + }, + + { + tag: "art-lojban", + options: { + region: "ZZ", + numberingSystem: "latn", + }, + canonical: "jbo-ZZ-u-nu-latn", + extensions: { + numberingSystem: "latn", + }, + }, +]; + +for (var {tag, options, canonical, extensions} of testData) { + var loc = new Intl.Locale(tag, options); + assertEq(loc.toString(), canonical); + + for (var [name, value] of Object.entries(extensions)) { + assertEq(loc[name], value); + } +} + +var errorTestData = [ + "en-gb-oed", + "i-default", + "sgn-ch-de", + "zh-min", + "zh-min-nan", + "zh-hakka-hakka", +]; + +for (var tag of errorTestData) { + assertThrowsInstanceOf(() => new Intl.Locale(tag), RangeError); + assertThrowsInstanceOf(() => new Intl.Locale(tag, {}), RangeError); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/Locale/likely-subtags-generated.js b/js/src/tests/non262/Intl/Locale/likely-subtags-generated.js new file mode 100644 index 0000000000..91d23ae663 --- /dev/null +++ b/js/src/tests/non262/Intl/Locale/likely-subtags-generated.js @@ -0,0 +1,15797 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')) +// Generated by make_intl_data.py. DO NOT EDIT. + +// Extracted from likelySubtags.xml. +// Derived from CLDR Supplemental Data, version 43. +// https://unicode.org/Public/cldr/43/cldr-common-43.0.zip +var maxLikelySubtags = { + "aa": "aa-Latn-ET", + "aaa": "aaa-Latn-NG", + "aab": "aab-Latn-NG", + "aac": "aac-Latn-PG", + "aad": "aad-Latn-PG", + "aae": "aae-Latn-IT", + "aae-Grek": "aae-Grek-IT", + "aaf": "aaf-Mlym-IN", + "aaf-Arab": "aaf-Arab-IN", + "aag": "aag-Latn-PG", + "aah": "aah-Latn-PG", + "aai": "aai-Latn-ZZ", + "aak": "aak-Latn-ZZ", + "aal": "aal-Latn-CM", + "aan": "aan-Latn-BR", + "aao": "aao-Arab-DZ", + "aap": "aap-Latn-BR", + "aaq": "aaq-Latn-US", + "aas": "aas-Latn-TZ", + "aat": "aat-Grek-GR", + "aau": "aau-Latn-ZZ", + "aaw": "aaw-Latn-PG", + "aax": "aax-Latn-ID", + "aaz": "aaz-Latn-ID", + "ab": "ab-Cyrl-GE", + "aba": "aba-Latn-CI", + "abb": "abb-Latn-CM", + "abc": "abc-Latn-PH", + "abd": "abd-Latn-PH", + "abe": "abe-Latn-CA", + "abf": "abf-Latn-MY", + "abg": "abg-Latn-PG", + "abh": "abh-Arab-TJ", + "abi": "abi-Latn-ZZ", + "abl": "abl-Rjng-ID", + "abl-Latn": "abl-Latn-ID", + "abm": "abm-Latn-NG", + "abn": "abn-Latn-NG", + "abo": "abo-Latn-NG", + "abp": "abp-Latn-PH", + "abq": "abq-Cyrl-ZZ", + "abr": "abr-Latn-GH", + "abs": "abs-Latn-ID", + "abt": "abt-Latn-ZZ", + "abu": "abu-Latn-CI", + "abv": "abv-Arab-BH", + "abw": "abw-Latn-PG", + "abx": "abx-Latn-PH", + "aby": "aby-Latn-ZZ", + "abz": "abz-Latn-ID", + "aca": "aca-Latn-CO", + "acb": "acb-Latn-NG", + "acd": "acd-Latn-ZZ", + "ace": "ace-Latn-ID", + "acf": "acf-Latn-LC", + "ach": "ach-Latn-UG", + "acm": "acm-Arab-IQ", + "acn": "acn-Latn-CN", + "acp": "acp-Latn-NG", + "acq": "acq-Arab-YE", + "acr": "acr-Latn-GT", + "acs": "acs-Latn-BR", + "act": "act-Latn-NL", + "acu": "acu-Latn-EC", + "acv": "acv-Latn-US", + "acw": "acw-Arab-SA", + "acx": "acx-Arab-OM", + "acy": "acy-Latn-CY", + "acy-Arab": "acy-Arab-CY", + "acy-Grek": "acy-Grek-CY", + "acz": "acz-Latn-SD", + "ada": "ada-Latn-GH", + "adb": "adb-Latn-TL", + "add": "add-Latn-CM", + "ade": "ade-Latn-ZZ", + "adf": "adf-Arab-OM", + "adg": "adg-Latn-AU", + "adh": "adh-Latn-UG", + "adi": "adi-Latn-IN", + "adi-Tibt": "adi-Tibt-CN", + "adj": "adj-Latn-ZZ", + "adl": "adl-Latn-IN", + "adn": "adn-Latn-ID", + "ado": "ado-Latn-PG", + "adp": "dz-Tibt-BT", + "adq": "adq-Latn-GH", + "adr": "adr-Latn-ID", + "adt": "adt-Latn-AU", + "adu": "adu-Latn-NG", + "adw": "adw-Latn-BR", + "adx": "adx-Tibt-CN", + "ady": "ady-Cyrl-RU", + "adz": "adz-Latn-ZZ", + "ae": "ae-Avst-IR", + "aea": "aea-Latn-AU", + "aeb": "aeb-Arab-TN", + "aec": "aec-Arab-EG", + "aee": "aee-Arab-AF", + "aek": "aek-Latn-NC", + "ael": "ael-Latn-CM", + "aem": "aem-Latn-VN", + "aeq": "aeq-Arab-PK", + "aer": "aer-Latn-AU", + "aeu": "aeu-Latn-CN", + "aew": "aew-Latn-PG", + "aey": "aey-Latn-ZZ", + "aez": "aez-Latn-PG", + "af": "af-Latn-ZA", + "afb": "afb-Arab-KW", + "afd": "afd-Latn-PG", + "afe": "afe-Latn-NG", + "afh": "afh-Latn-GH", + "afi": "afi-Latn-PG", + "afk": "afk-Latn-PG", + "afn": "afn-Latn-NG", + "afo": "afo-Latn-NG", + "afp": "afp-Latn-PG", + "afs": "afs-Latn-MX", + "afu": "afu-Latn-GH", + "afz": "afz-Latn-ID", + "aga": "aga-Latn-PE", + "agb": "agb-Latn-NG", + "agc": "agc-Latn-ZZ", + "agd": "agd-Latn-ZZ", + "age": "age-Latn-PG", + "agf": "agf-Latn-ID", + "agg": "agg-Latn-ZZ", + "agh": "agh-Latn-CD", + "agi": "agi-Deva-IN", + "agj": "agj-Ethi-ET", + "agj-Arab": "agj-Arab-ET", + "agk": "agk-Latn-PH", + "agl": "agl-Latn-PG", + "agm": "agm-Latn-ZZ", + "agn": "agn-Latn-PH", + "ago": "ago-Latn-ZZ", + "agq": "agq-Latn-CM", + "agr": "agr-Latn-PE", + "ags": "ags-Latn-CM", + "agt": "agt-Latn-PH", + "agu": "agu-Latn-GT", + "agv": "agv-Latn-PH", + "agw": "agw-Latn-SB", + "agx": "agx-Cyrl-RU", + "agy": "agy-Latn-PH", + "agz": "agz-Latn-PH", + "aha": "aha-Latn-ZZ", + "ahb": "ahb-Latn-VU", + "ahg": "ahg-Ethi-ET", + "ahh": "ahh-Latn-ID", + "ahi": "ahi-Latn-CI", + "ahk": "ahk-Latn-MM", + "ahk-Mymr": "ahk-Mymr-MM", + "ahk-TH": "ahk-Latn-TH", + "ahk-Thai": "ahk-Thai-TH", + "ahl": "ahl-Latn-ZZ", + "ahm": "ahm-Latn-CI", + "ahn": "ahn-Latn-NG", + "aho": "aho-Ahom-IN", + "ahp": "ahp-Latn-CI", + "ahr": "ahr-Deva-IN", + "ahs": "ahs-Latn-NG", + "aht": "aht-Latn-US", + "aia": "aia-Latn-SB", + "aib": "aib-Arab-CN", + "aic": "aic-Latn-PG", + "aid": "aid-Latn-AU", + "aie": "aie-Latn-PG", + "aif": "aif-Latn-PG", + "aig": "aig-Latn-AG", + "aij": "aij-Hebr-IL", + "aik": "aik-Latn-NG", + "ail": "ail-Latn-PG", + "aim": "aim-Latn-IN", + "ain": "ain-Kana-JP", + "ain-Latn": "ain-Latn-JP", + "aio": "aio-Mymr-IN", + "aip": "aip-Latn-ID", + "aiq": "aiq-Arab-AF", + "air": "air-Latn-ID", + "ait": "ait-Latn-BR", + "aiw": "aiw-Latn-ET", + "aiw-Arab": "aiw-Arab-ET", + "aiw-Ethi": "aiw-Ethi-ET", + "aix": "aix-Latn-PG", + "aiy": "aiy-Latn-CF", + "aja": "aja-Latn-SS", + "ajg": "ajg-Latn-ZZ", + "aji": "aji-Latn-NC", + "ajn": "ajn-Latn-AU", + "ajp": "ajp-Arab-JO", + "ajt": "aeb-Arab-TN", + "ajw": "ajw-Latn-NG", + "ajz": "ajz-Latn-IN", + "ak": "ak-Latn-GH", + "akb": "akb-Latn-ID", + "akb-Batk": "akb-Batk-ID", + "akc": "akc-Latn-ID", + "akd": "akd-Latn-NG", + "ake": "ake-Latn-GY", + "akf": "akf-Latn-NG", + "akg": "akg-Latn-ID", + "akh": "akh-Latn-PG", + "aki": "aki-Latn-PG", + "akk": "akk-Xsux-IQ", + "akl": "akl-Latn-PH", + "ako": "ako-Latn-SR", + "akp": "akp-Latn-GH", + "akq": "akq-Latn-PG", + "akr": "akr-Latn-VU", + "aks": "aks-Latn-TG", + "akt": "akt-Latn-PG", + "aku": "aku-Latn-CM", + "akv": "akv-Cyrl-RU", + "akw": "akw-Latn-CG", + "akz": "akz-Latn-US", + "ala": "ala-Latn-ZZ", + "alc": "alc-Latn-CL", + "ald": "ald-Latn-CI", + "ale": "ale-Latn-US", + "alf": "alf-Latn-NG", + "alh": "alh-Latn-AU", + "ali": "ali-Latn-ZZ", + "alj": "alj-Latn-PH", + "alk": "alk-Laoo-LA", + "all": "all-Mlym-IN", + "alm": "alm-Latn-VU", + "aln": "aln-Latn-XK", + "alo": "alo-Latn-ID", + "alp": "alp-Latn-ID", + "alq": "alq-Latn-CA", + "alr": "alr-Cyrl-RU", + "alt": "alt-Cyrl-RU", + "alu": "alu-Latn-SB", + "alw": "alw-Ethi-ET", + "alx": "alx-Latn-PG", + "aly": "aly-Latn-AU", + "alz": "alz-Latn-CD", + "am": "am-Ethi-ET", + "ama": "ama-Latn-BR", + "amb": "amb-Latn-NG", + "amc": "amc-Latn-PE", + "ame": "ame-Latn-PE", + "amf": "amf-Latn-ET", + "amf-Ethi": "amf-Ethi-ET", + "amg": "amg-Latn-AU", + "ami": "ami-Latn-TW", + "amj": "amj-Latn-TD", + "amk": "amk-Latn-ID", + "amm": "amm-Latn-ZZ", + "amn": "amn-Latn-ZZ", + "amo": "amo-Latn-NG", + "amp": "amp-Latn-ZZ", + "amq": "amq-Latn-ID", + "amr": "amr-Latn-PE", + "ams": "ams-Jpan-JP", + "amt": "amt-Latn-PG", + "amu": "amu-Latn-MX", + "amv": "amv-Latn-ID", + "amw": "amw-Syrc-SY", + "amw-Arab": "amw-Arab-SY", + "amw-Armi": "amw-Armi-SY", + "amw-Latn": "amw-Latn-SY", + "amx": "amx-Latn-AU", + "amy": "amy-Latn-AU", + "amz": "amz-Latn-AU", + "an": "an-Latn-ES", + "ana": "ana-Latn-CO", + "anb": "anb-Latn-PE", + "anc": "anc-Latn-ZZ", + "and": "and-Latn-ID", + "ane": "ane-Latn-NC", + "anf": "anf-Latn-GH", + "ang": "ang-Latn-GB", + "anh": "anh-Latn-PG", + "ani": "ani-Cyrl-RU", + "anj": "anj-Latn-PG", + "ank": "ank-Latn-ZZ", + "anl": "anl-Latn-MM", + "anm": "anm-Latn-IN", + "ann": "ann-Latn-NG", + "ano": "ano-Latn-CO", + "anp": "anp-Deva-IN", + "anr": "anr-Deva-IN", + "ans": "ans-Latn-CO", + "ant": "ant-Latn-AU", + "anu": "anu-Ethi-ET", + "anu-Arab": "anu-Arab-SS", + "anu-Latn": "anu-Latn-SS", + "anv": "anv-Latn-CM", + "anw": "anw-Latn-NG", + "anx": "anx-Latn-PG", + "any": "any-Latn-ZZ", + "anz": "anz-Latn-PG", + "aoa": "aoa-Latn-ST", + "aob": "aob-Latn-PG", + "aoc": "aoc-Latn-VE", + "aod": "aod-Latn-PG", + "aoe": "aoe-Latn-PG", + "aof": "aof-Latn-PG", + "aog": "aog-Latn-PG", + "aoi": "aoi-Latn-AU", + "aoj": "aoj-Latn-ZZ", + "aok": "aok-Latn-NC", + "aol": "aol-Latn-ID", + "aom": "aom-Latn-ZZ", + "aon": "aon-Latn-PG", + "aor": "aor-Latn-VU", + "aos": "aos-Latn-ID", + "aot": "aot-Beng-BD", + "aot-Latn": "aot-Latn-IN", + "aox": "aox-Latn-GY", + "aoz": "aoz-Latn-ID", + "apb": "apb-Latn-SB", + "apc": "apc-Arab-SY", + "apd": "apd-Arab-TG", + "ape": "ape-Latn-ZZ", + "apf": "apf-Latn-PH", + "apg": "apg-Latn-ID", + "aph": "aph-Deva-NP", + "api": "api-Latn-BR", + "apj": "apj-Latn-US", + "apk": "apk-Latn-US", + "apl": "apl-Latn-US", + "apm": "apm-Latn-US", + "apn": "apn-Latn-BR", + "apo": "apo-Latn-PG", + "app": "app-Latn-VU", + "apr": "apr-Latn-ZZ", + "aps": "aps-Latn-ZZ", + "apt": "apt-Latn-IN", + "apu": "apu-Latn-BR", + "apv": "apv-Latn-BR", + "apw": "apw-Latn-US", + "apx": "apx-Latn-ID", + "apy": "apy-Latn-BR", + "apz": "apz-Latn-ZZ", + "aqc": "aqc-Cyrl-RU", + "aqd": "aqd-Latn-ML", + "aqg": "aqg-Latn-NG", + "aqk": "aqk-Latn-NG", + "aqm": "aqm-Latn-ID", + "aqn": "aqn-Latn-PH", + "aqr": "aqr-Latn-NC", + "aqt": "aqt-Latn-PY", + "aqz": "aqz-Latn-BR", + "ar": "ar-Arab-EG", + "arc": "arc-Armi-IR", + "arc-Nbat": "arc-Nbat-JO", + "arc-Palm": "arc-Palm-SY", + "ard": "ard-Latn-AU", + "are": "are-Latn-AU", + "arh": "arh-Latn-ZZ", + "ari": "ari-Latn-US", + "arj": "arj-Latn-BR", + "ark": "ark-Latn-BR", + "arl": "arl-Latn-PE", + "arn": "arn-Latn-CL", + "aro": "aro-Latn-BO", + "arp": "arp-Latn-US", + "arq": "arq-Arab-DZ", + "arr": "arr-Latn-BR", + "ars": "ars-Arab-SA", + "aru": "aru-Latn-BR", + "arw": "arw-Latn-SR", + "arx": "arx-Latn-BR", + "ary": "ary-Arab-MA", + "arz": "arz-Arab-EG", + "as": "as-Beng-IN", + "asa": "asa-Latn-TZ", + "asb": "asb-Latn-CA", + "asc": "asc-Latn-ID", + "ase": "ase-Sgnw-US", + "asg": "asg-Latn-ZZ", + "ash": "ash-Latn-PE", + "asi": "asi-Latn-ID", + "asj": "asj-Latn-CM", + "ask": "ask-Arab-AF", + "asl": "asl-Latn-ID", + "asn": "asn-Latn-BR", + "aso": "aso-Latn-ZZ", + "ass": "ass-Latn-CM", + "ast": "ast-Latn-ES", + "asu": "asu-Latn-BR", + "asv": "asv-Latn-CD", + "asx": "asx-Latn-PG", + "asy": "asy-Latn-ID", + "asz": "asz-Latn-ID", + "ata": "ata-Latn-ZZ", + "atb": "atb-Latn-CN", + "atb-Lisu": "atb-Lisu-CN", + "atc": "atc-Latn-PE", + "atd": "atd-Latn-PH", + "ate": "ate-Latn-PG", + "atg": "atg-Latn-ZZ", + "ati": "ati-Latn-CI", + "atj": "atj-Latn-CA", + "atk": "atk-Latn-PH", + "atl": "atl-Latn-PH", + "atm": "atm-Latn-PH", + "atn": "atn-Arab-IR", + "ato": "ato-Latn-CM", + "atp": "atp-Latn-PH", + "atq": "atq-Latn-ID", + "atr": "atr-Latn-BR", + "ats": "ats-Latn-US", + "att": "att-Latn-PH", + "atu": "atu-Latn-SS", + "atv": "atv-Cyrl-RU", + "atw": "atw-Latn-US", + "atx": "atx-Latn-BR", + "aty": "aty-Latn-VU", + "atz": "atz-Latn-PH", + "aua": "aua-Latn-SB", + "auc": "auc-Latn-EC", + "aud": "aud-Latn-SB", + "aug": "aug-Latn-BJ", + "auh": "auh-Latn-ZM", + "aui": "aui-Latn-PG", + "auj": "auj-Arab-LY", + "auj-Latn": "auj-Latn-LY", + "auj-Tfng": "auj-Tfng-LY", + "auk": "auk-Latn-PG", + "aul": "aul-Latn-VU", + "aum": "aum-Latn-NG", + "aun": "aun-Latn-PG", + "auo": "auo-Latn-NG", + "aup": "aup-Latn-PG", + "auq": "auq-Latn-ID", + "aur": "aur-Latn-PG", + "aut": "aut-Latn-PF", + "auu": "auu-Latn-ID", + "auw": "auw-Latn-ID", + "auy": "auy-Latn-ZZ", + "auz": "auz-Arab-UZ", + "av": "av-Cyrl-RU", + "avb": "avb-Latn-PG", + "avd": "avd-Arab-IR", + "avi": "avi-Latn-CI", + "avk": "avk-Latn-001", + "avl": "avl-Arab-ZZ", + "avm": "avm-Latn-AU", + "avn": "avn-Latn-ZZ", + "avo": "avo-Latn-BR", + "avs": "avs-Latn-PE", + "avt": "avt-Latn-ZZ", + "avu": "avu-Latn-ZZ", + "avv": "avv-Latn-BR", + "awa": "awa-Deva-IN", + "awb": "awb-Latn-ZZ", + "awc": "awc-Latn-NG", + "awe": "awe-Latn-BR", + "awg": "awg-Latn-AU", + "awh": "awh-Latn-ID", + "awi": "awi-Latn-PG", + "awk": "awk-Latn-AU", + "awm": "awm-Latn-PG", + "awn": "awn-Ethi-ET", + "awo": "awo-Latn-ZZ", + "awr": "awr-Latn-ID", + "aws": "aws-Latn-ID", + "awt": "awt-Latn-BR", + "awu": "awu-Latn-ID", + "awv": "awv-Latn-ID", + "aww": "aww-Latn-PG", + "awx": "awx-Latn-ZZ", + "awy": "awy-Latn-ID", + "axb": "axb-Latn-AR", + "axe": "axe-Latn-AU", + "axg": "axg-Latn-BR", + "axk": "axk-Latn-CF", + "axl": "axl-Latn-AU", + "axm": "axm-Armn-AM", + "axx": "axx-Latn-NC", + "ay": "ay-Latn-BO", + "aya": "aya-Latn-PG", + "ayb": "ayb-Latn-ZZ", + "ayc": "ayc-Latn-PE", + "ayd": "ayd-Latn-AU", + "aye": "aye-Latn-NG", + "ayg": "ayg-Latn-TG", + "ayh": "ayh-Arab-YE", + "ayi": "ayi-Latn-NG", + "ayk": "ayk-Latn-NG", + "ayl": "ayl-Arab-LY", + "ayn": "ayn-Arab-YE", + "ayo": "ayo-Latn-PY", + "ayp": "ayp-Arab-IQ", + "ayq": "ayq-Latn-PG", + "ays": "ays-Latn-PH", + "ayt": "ayt-Latn-PH", + "ayu": "ayu-Latn-NG", + "ayz": "ayz-Latn-ID", + "az": "az-Latn-AZ", + "az-Arab": "az-Arab-IR", + "az-IQ": "az-Arab-IQ", + "az-IR": "az-Arab-IR", + "az-RU": "az-Cyrl-RU", + "azb": "azb-Arab-IR", + "azb-Cyrl": "azb-Cyrl-AZ", + "azb-Latn": "azb-Latn-AZ", + "azd": "azd-Latn-MX", + "azg": "azg-Latn-MX", + "azm": "azm-Latn-MX", + "azn": "azn-Latn-MX", + "azo": "azo-Latn-CM", + "azt": "azt-Latn-PH", + "azz": "azz-Latn-MX", + "ba": "ba-Cyrl-RU", + "baa": "baa-Latn-SB", + "bab": "bab-Latn-GW", + "bac": "bac-Latn-ID", + "bae": "bae-Latn-VE", + "baf": "baf-Latn-CM", + "bag": "bag-Latn-CM", + "bah": "bah-Latn-BS", + "baj": "baj-Latn-ID", + "bal": "bal-Arab-PK", + "ban": "ban-Latn-ID", + "bao": "bao-Latn-CO", + "bap": "bap-Deva-NP", + "bar": "bar-Latn-AT", + "bas": "bas-Latn-CM", + "bau": "bau-Latn-NG", + "bav": "bav-Latn-ZZ", + "baw": "baw-Latn-CM", + "bax": "bax-Bamu-CM", + "bay": "bay-Latn-ID", + "bba": "bba-Latn-ZZ", + "bbb": "bbb-Latn-ZZ", + "bbc": "bbc-Latn-ID", + "bbd": "bbd-Latn-ZZ", + "bbe": "bbe-Latn-CD", + "bbf": "bbf-Latn-PG", + "bbg": "bbg-Latn-GA", + "bbi": "bbi-Latn-CM", + "bbj": "bbj-Latn-CM", + "bbk": "bbk-Latn-CM", + "bbl": "bbl-Geor-GE", + "bbm": "bbm-Latn-CD", + "bbn": "bbn-Latn-PG", + "bbo": "bbo-Latn-BF", + "bbp": "bbp-Latn-ZZ", + "bbq": "bbq-Latn-CM", + "bbr": "bbr-Latn-ZZ", + "bbs": "bbs-Latn-NG", + "bbt": "bbt-Latn-NG", + "bbu": "bbu-Latn-NG", + "bbv": "bbv-Latn-PG", + "bbw": "bbw-Latn-CM", + "bbx": "bbx-Latn-CM", + "bby": "bby-Latn-CM", + "bca": "bca-Latn-CN", + "bca-Hani": "bca-Hani-CN", + "bcb": "bcb-Latn-SN", + "bcd": "bcd-Latn-ID", + "bce": "bce-Latn-CM", + "bcf": "bcf-Latn-ZZ", + "bcg": "bcg-Latn-GN", + "bch": "bch-Latn-ZZ", + "bci": "bci-Latn-CI", + "bcj": "bcj-Latn-AU", + "bck": "bck-Latn-AU", + "bcm": "bcm-Latn-ZZ", + "bcn": "bcn-Latn-ZZ", + "bco": "bco-Latn-ZZ", + "bcp": "bcp-Latn-CD", + "bcq": "bcq-Ethi-ZZ", + "bcr": "bcr-Latn-CA", + "bcs": "bcs-Latn-NG", + "bct": "bct-Latn-CD", + "bcu": "bcu-Latn-ZZ", + "bcv": "bcv-Latn-NG", + "bcw": "bcw-Latn-CM", + "bcy": "bcy-Latn-NG", + "bcz": "bcz-Latn-SN", + "bda": "bda-Latn-SN", + "bdb": "bdb-Latn-ID", + "bdc": "bdc-Latn-CO", + "bdd": "bdd-Latn-ZZ", + "bde": "bde-Latn-NG", + "bdf": "bdf-Latn-PG", + "bdg": "bdg-Latn-MY", + "bdh": "bdh-Latn-SS", + "bdi": "bdi-Latn-SD", + "bdj": "bdj-Latn-SS", + "bdk": "bdk-Latn-AZ", + "bdl": "bdl-Latn-ID", + "bdm": "bdm-Latn-TD", + "bdn": "bdn-Latn-CM", + "bdo": "bdo-Latn-TD", + "bdp": "bdp-Latn-TZ", + "bdq": "bdq-Latn-VN", + "bdr": "bdr-Latn-MY", + "bds": "bds-Latn-TZ", + "bdt": "bdt-Latn-CF", + "bdu": "bdu-Latn-CM", + "bdv": "bdv-Orya-IN", + "bdw": "bdw-Latn-ID", + "bdx": "bdx-Latn-ID", + "bdy": "bdy-Latn-AU", + "bdz": "bdz-Arab-PK", + "be": "be-Cyrl-BY", + "bea": "bea-Latn-CA", + "bea-Cans": "bea-Cans-CA", + "beb": "beb-Latn-CM", + "bec": "bec-Latn-CM", + "bed": "bed-Latn-ID", + "bee": "bee-Deva-IN", + "bef": "bef-Latn-ZZ", + "beh": "beh-Latn-ZZ", + "bei": "bei-Latn-ID", + "bej": "bej-Arab-SD", + "bek": "bek-Latn-PG", + "bem": "bem-Latn-ZM", + "beo": "beo-Latn-PG", + "bep": "bep-Latn-ID", + "beq": "beq-Latn-CG", + "bes": "bes-Latn-TD", + "bet": "bet-Latn-ZZ", + "beu": "beu-Latn-ID", + "bev": "bev-Latn-CI", + "bew": "bew-Latn-ID", + "bex": "bex-Latn-ZZ", + "bey": "bey-Latn-PG", + "bez": "bez-Latn-TZ", + "bfa": "bfa-Latn-SS", + "bfa-Arab": "bfa-Arab-SS", + "bfb": "bfb-Deva-IN", + "bfc": "bfc-Latn-CN", + "bfd": "bfd-Latn-CM", + "bfe": "bfe-Latn-ID", + "bff": "bff-Latn-CF", + "bfg": "bfg-Latn-ID", + "bfh": "bfh-Latn-PG", + "bfj": "bfj-Latn-CM", + "bfl": "bfl-Latn-CF", + "bfm": "bfm-Latn-CM", + "bfn": "bfn-Latn-TL", + "bfo": "bfo-Latn-BF", + "bfp": "bfp-Latn-CM", + "bfq": "bfq-Taml-IN", + "bfs": "bfs-Latn-CN", + "bfs-Hani": "bfs-Hani-CN", + "bft": "bft-Arab-PK", + "bfu": "bfu-Tibt-IN", + "bfu-Takr": "bfu-Takr-IN", + "bfw": "bfw-Orya-IN", + "bfx": "bfx-Latn-PH", + "bfy": "bfy-Deva-IN", + "bfz": "bfz-Deva-IN", + "bg": "bg-Cyrl-BG", + "bga": "bga-Latn-NG", + "bgb": "bgb-Latn-ID", + "bgc": "bgc-Deva-IN", + "bgd": "bgd-Deva-IN", + "bgf": "bgf-Latn-CM", + "bgg": "bgg-Latn-IN", + "bgi": "bgi-Latn-PH", + "bgj": "bgj-Latn-CM", + "bgn": "bgn-Arab-PK", + "bgo": "bgo-Latn-GN", + "bgp": "bgp-Arab-PK", + "bgq": "bgq-Deva-IN", + "bgr": "bgr-Latn-IN", + "bgs": "bgs-Latn-PH", + "bgt": "bgt-Latn-SB", + "bgu": "bgu-Latn-NG", + "bgv": "bgv-Latn-ID", + "bgw": "bgw-Deva-IN", + "bgx": "bgx-Grek-TR", + "bgy": "bgy-Latn-ID", + "bgz": "bgz-Latn-ID", + "bha": "bha-Deva-IN", + "bhb": "bhb-Deva-IN", + "bhc": "bhc-Latn-ID", + "bhd": "bhd-Deva-IN", + "bhd-Arab": "bhd-Arab-IN", + "bhd-Takr": "bhd-Takr-IN", + "bhe": "bhe-Arab-PK", + "bhf": "bhf-Latn-PG", + "bhg": "bhg-Latn-ZZ", + "bhh": "bhh-Cyrl-IL", + "bhh-Hebr": "bhh-Hebr-IL", + "bhh-Latn": "bhh-Latn-IL", + "bhi": "bhi-Deva-IN", + "bhj": "bhj-Deva-NP", + "bhl": "bhl-Latn-ZZ", + "bhm": "bhm-Arab-OM", + "bhn": "bhn-Syrc-GE", + "bho": "bho-Deva-IN", + "bhp": "bhp-Latn-ID", + "bhq": "bhq-Latn-ID", + "bhr": "bhr-Latn-MG", + "bhs": "bhs-Latn-CM", + "bht": "bht-Takr-IN", + "bht-Deva": "bht-Deva-IN", + "bht-Latn": "bht-Latn-IN", + "bhu": "bhu-Deva-IN", + "bhv": "bhv-Latn-ID", + "bhw": "bhw-Latn-ID", + "bhy": "bhy-Latn-ZZ", + "bhz": "bhz-Latn-ID", + "bi": "bi-Latn-VU", + "bia": "bia-Latn-AU", + "bib": "bib-Latn-ZZ", + "bid": "bid-Latn-TD", + "bie": "bie-Latn-PG", + "bif": "bif-Latn-GW", + "big": "big-Latn-ZZ", + "bik": "bik-Latn-PH", + "bil": "bil-Latn-NG", + "bim": "bim-Latn-ZZ", + "bin": "bin-Latn-NG", + "bio": "bio-Latn-ZZ", + "bip": "bip-Latn-CD", + "biq": "biq-Latn-ZZ", + "bir": "bir-Latn-PG", + "bit": "bit-Latn-PG", + "biu": "biu-Latn-IN", + "biv": "biv-Latn-GH", + "biw": "biw-Latn-CM", + "biy": "biy-Deva-IN", + "biz": "biz-Latn-CD", + "bja": "bja-Latn-CD", + "bjb": "bjb-Latn-AU", + "bjc": "bjc-Latn-PG", + "bjf": "bjf-Syrc-IL", + "bjg": "bjg-Latn-GW", + "bjh": "bjh-Latn-ZZ", + "bji": "bji-Ethi-ZZ", + "bjj": "bjj-Deva-IN", + "bjk": "bjk-Latn-PG", + "bjl": "bjl-Latn-PG", + "bjm": "bjm-Arab-IQ", + "bjn": "bjn-Latn-ID", + "bjo": "bjo-Latn-ZZ", + "bjp": "bjp-Latn-PG", + "bjr": "bjr-Latn-ZZ", + "bjs": "bjs-Latn-BB", + "bjt": "bjt-Latn-SN", + "bju": "bju-Latn-CM", + "bjv": "bjv-Latn-TD", + "bjw": "bjw-Latn-CI", + "bjx": "bjx-Latn-PH", + "bjy": "bjy-Latn-AU", + "bjz": "bjz-Latn-ZZ", + "bka": "bka-Latn-NG", + "bkc": "bkc-Latn-ZZ", + "bkd": "bkd-Latn-PH", + "bkf": "bkf-Latn-CD", + "bkg": "bkg-Latn-CF", + "bkh": "bkh-Latn-CM", + "bki": "bki-Latn-VU", + "bkj": "bkj-Latn-CF", + "bkl": "bkl-Latn-ID", + "bkm": "bkm-Latn-CM", + "bkn": "bkn-Latn-ID", + "bko": "bko-Latn-CM", + "bkp": "bkp-Latn-CD", + "bkq": "bkq-Latn-ZZ", + "bkr": "bkr-Latn-ID", + "bks": "bks-Latn-PH", + "bkt": "bkt-Latn-CD", + "bku": "bku-Latn-PH", + "bkv": "bkv-Latn-ZZ", + "bkw": "bkw-Latn-CG", + "bkx": "bkx-Latn-TL", + "bky": "bky-Latn-NG", + "bkz": "bkz-Latn-ID", + "bla": "bla-Latn-CA", + "blb": "blb-Latn-SB", + "blc": "blc-Latn-CA", + "bld": "bld-Latn-ID", + "ble": "ble-Latn-GW", + "blf": "blf-Latn-ID", + "blg": "iba-Latn-MY", + "blh": "blh-Latn-LR", + "bli": "bli-Latn-CD", + "blj": "blj-Latn-ID", + "blk": "blk-Mymr-MM", + "blm": "blm-Latn-SS", + "bln": "bln-Latn-PH", + "blo": "blo-Latn-BJ", + "blp": "blp-Latn-SB", + "blq": "blq-Latn-PG", + "blr": "blr-Latn-CN", + "blr-Tale": "blr-Tale-CN", + "blr-Thai": "blr-Thai-TH", + "bls": "bls-Latn-ID", + "blt": "blt-Tavt-VN", + "blv": "blv-Latn-AO", + "blw": "blw-Latn-PH", + "blx": "blx-Latn-PH", + "bly": "bly-Latn-BJ", + "blz": "blz-Latn-ID", + "bm": "bm-Latn-ML", + "bma": "bma-Latn-NG", + "bmb": "bmb-Latn-CD", + "bmc": "bmc-Latn-PG", + "bmd": "bmd-Latn-GN", + "bme": "bme-Latn-CF", + "bmf": "bmf-Latn-SL", + "bmg": "bmg-Latn-CD", + "bmh": "bmh-Latn-ZZ", + "bmi": "bmi-Latn-TD", + "bmj": "bmj-Deva-NP", + "bmk": "bmk-Latn-ZZ", + "bml": "bml-Latn-CD", + "bmm": "bmm-Latn-MG", + "bmn": "bmn-Latn-PG", + "bmo": "bmo-Latn-CM", + "bmp": "bmp-Latn-PG", + "bmq": "bmq-Latn-ML", + "bmr": "bmr-Latn-CO", + "bms": "bms-Latn-NE", + "bmu": "bmu-Latn-ZZ", + "bmv": "bmv-Latn-CM", + "bmw": "bmw-Latn-CG", + "bmx": "bmx-Latn-PG", + "bmz": "bmz-Latn-PG", + "bn": "bn-Beng-BD", + "bna": "bna-Latn-ID", + "bnb": "bnb-Latn-MY", + "bnc": "bnc-Latn-PH", + "bnd": "bnd-Latn-ID", + "bne": "bne-Latn-ID", + "bnf": "bnf-Latn-ID", + "bng": "bng-Latn-ZZ", + "bni": "bni-Latn-CD", + "bnj": "bnj-Latn-PH", + "bnk": "bnk-Latn-VU", + "bnm": "bnm-Latn-ZZ", + "bnn": "bnn-Latn-TW", + "bno": "bno-Latn-PH", + "bnp": "bnp-Latn-ZZ", + "bnq": "bnq-Latn-ID", + "bnr": "bnr-Latn-VU", + "bns": "bns-Deva-IN", + "bnu": "bnu-Latn-ID", + "bnv": "bnv-Latn-ID", + "bnw": "bnw-Latn-PG", + "bnx": "bnx-Latn-CD", + "bny": "bny-Latn-MY", + "bnz": "bnz-Latn-CM", + "bo": "bo-Tibt-CN", + "boa": "boa-Latn-PE", + "bob": "bob-Latn-KE", + "boe": "boe-Latn-CM", + "bof": "bof-Latn-BF", + "boh": "boh-Latn-CD", + "boj": "boj-Latn-ZZ", + "bok": "bok-Latn-CG", + "bol": "bol-Latn-NG", + "bom": "bom-Latn-ZZ", + "bon": "bon-Latn-ZZ", + "boo": "boo-Latn-ML", + "bop": "bop-Latn-PG", + "boq": "boq-Latn-PG", + "bor": "bor-Latn-BR", + "bot": "bot-Latn-SS", + "bou": "bou-Latn-TZ", + "bov": "bov-Latn-GH", + "bow": "bow-Latn-PG", + "box": "box-Latn-BF", + "boy": "boy-Latn-CF", + "boz": "boz-Latn-ML", + "boz-Arab": "boz-Arab-ML", + "bpa": "bpa-Latn-VU", + "bpc": "bpc-Latn-CM", + "bpd": "bpd-Latn-CF", + "bpe": "bpe-Latn-PG", + "bpg": "bpg-Latn-ID", + "bph": "bph-Cyrl-RU", + "bpi": "bpi-Latn-PG", + "bpj": "bpj-Latn-CD", + "bpk": "bpk-Latn-NC", + "bpl": "bpl-Latn-AU", + "bpm": "bpm-Latn-PG", + "bpo": "bpo-Latn-ID", + "bpp": "bpp-Latn-ID", + "bpq": "bpq-Latn-ID", + "bpr": "bpr-Latn-PH", + "bps": "bps-Latn-PH", + "bpt": "bpt-Latn-AU", + "bpu": "bpu-Latn-PG", + "bpv": "bpv-Latn-ID", + "bpw": "bpw-Latn-PG", + "bpx": "bpx-Deva-IN", + "bpy": "bpy-Beng-IN", + "bpz": "bpz-Latn-ID", + "bqa": "bqa-Latn-BJ", + "bqb": "bqb-Latn-ID", + "bqc": "bqc-Latn-ZZ", + "bqd": "bqd-Latn-CM", + "bqf": "bqf-Latn-GN", + "bqf-Arab": "bqf-Arab-GN", + "bqg": "bqg-Latn-TG", + "bqi": "bqi-Arab-IR", + "bqj": "bqj-Latn-SN", + "bqk": "bqk-Latn-CF", + "bql": "bql-Latn-PG", + "bqm": "bqm-Latn-CM", + "bqo": "bqo-Latn-CM", + "bqp": "bqp-Latn-ZZ", + "bqq": "bqq-Latn-ID", + "bqr": "bqr-Latn-ID", + "bqs": "bqs-Latn-PG", + "bqt": "bqt-Latn-CM", + "bqu": "bqu-Latn-CD", + "bqv": "bqv-Latn-CI", + "bqw": "bqw-Latn-NG", + "bqx": "bqx-Latn-NG", + "bqz": "bqz-Latn-CM", + "br": "br-Latn-FR", + "bra": "bra-Deva-IN", + "brb": "brb-Khmr-KH", + "brb-Laoo": "brb-Laoo-LA", + "brb-Latn": "brb-Latn-VN", + "brc": "brc-Latn-GY", + "brd": "brd-Deva-NP", + "brf": "brf-Latn-CD", + "brg": "brg-Latn-BO", + "brh": "brh-Arab-PK", + "bri": "bri-Latn-CM", + "brj": "brj-Latn-VU", + "brk": "brk-Arab-SD", + "brl": "brl-Latn-BW", + "brm": "brm-Latn-CD", + "brn": "brn-Latn-CR", + "brp": "brp-Latn-ID", + "brq": "brq-Latn-PG", + "brr": "brr-Latn-SB", + "brs": "brs-Latn-ID", + "brt": "brt-Latn-NG", + "bru": "bru-Latn-VN", + "bru-Laoo": "bru-Laoo-LA", + "bru-Thai": "bru-Thai-LA", + "brv": "brv-Laoo-LA", + "brx": "brx-Deva-IN", + "bry": "bry-Latn-PG", + "brz": "brz-Latn-ZZ", + "bs": "bs-Latn-BA", + "bsa": "bsa-Latn-ID", + "bsb": "bsb-Latn-BN", + "bsc": "bsc-Latn-SN", + "bse": "bse-Latn-CM", + "bsf": "bsf-Latn-NG", + "bsh": "bsh-Arab-AF", + "bsi": "bsi-Latn-CM", + "bsj": "bsj-Latn-ZZ", + "bsk": "bsk-Arab-PK", + "bsk-Latn": "bsk-Latn-PK", + "bsl": "bsl-Latn-NG", + "bsm": "bsm-Latn-ID", + "bsn": "bsn-Latn-CO", + "bso": "bso-Latn-TD", + "bsp": "bsp-Latn-GN", + "bsq": "bsq-Bass-LR", + "bsr": "bsr-Latn-NG", + "bss": "bss-Latn-CM", + "bst": "bst-Ethi-ZZ", + "bsu": "bsu-Latn-ID", + "bsv": "bsv-Latn-GN", + "bsv-Arab": "bsv-Arab-GN", + "bsw": "bsw-Latn-ET", + "bsw-Ethi": "bsw-Ethi-ET", + "bsx": "bsx-Latn-NG", + "bsy": "bsy-Latn-MY", + "bta": "bta-Latn-NG", + "btc": "btc-Latn-CM", + "btd": "btd-Batk-ID", + "bte": "bte-Latn-NG", + "btf": "btf-Latn-TD", + "btg": "btg-Latn-CI", + "bth": "bth-Latn-MY", + "bti": "bti-Latn-ID", + "btj": "btj-Latn-ID", + "btm": "btm-Batk-ID", + "btn": "btn-Latn-PH", + "bto": "bto-Latn-PH", + "btp": "btp-Latn-PG", + "btq": "btq-Latn-MY", + "btr": "btr-Latn-VU", + "bts": "bts-Latn-ID", + "bts-Batk": "bts-Batk-ID", + "btt": "btt-Latn-ZZ", + "btu": "btu-Latn-NG", + "btv": "btv-Deva-PK", + "btw": "btw-Latn-PH", + "btx": "btx-Latn-ID", + "btx-Batk": "btx-Batk-ID", + "bty": "bty-Latn-ID", + "btz": "btz-Latn-ID", + "bua": "bua-Cyrl-RU", + "bub": "bub-Latn-TD", + "buc": "buc-Latn-YT", + "bud": "bud-Latn-ZZ", + "bue": "bue-Latn-CA", + "buf": "buf-Latn-CD", + "bug": "bug-Latn-ID", + "buh": "buh-Latn-CN", + "bui": "bui-Latn-CG", + "buj": "buj-Latn-NG", + "buk": "buk-Latn-ZZ", + "bum": "bum-Latn-CM", + "bun": "bun-Latn-SL", + "buo": "buo-Latn-ZZ", + "bup": "bup-Latn-ID", + "buq": "buq-Latn-PG", + "bus": "bus-Latn-ZZ", + "but": "but-Latn-PG", + "buu": "buu-Latn-ZZ", + "buv": "buv-Latn-PG", + "buw": "buw-Latn-GA", + "bux": "bux-Latn-NG", + "buy": "buy-Latn-SL", + "buz": "buz-Latn-NG", + "bva": "bva-Latn-TD", + "bvb": "bvb-Latn-GQ", + "bvc": "bvc-Latn-SB", + "bvd": "bvd-Latn-SB", + "bve": "bve-Latn-ID", + "bvf": "bvf-Latn-TD", + "bvg": "bvg-Latn-CM", + "bvh": "bvh-Latn-NG", + "bvi": "bvi-Latn-SS", + "bvj": "bvj-Latn-NG", + "bvk": "bvk-Latn-ID", + "bvm": "bvm-Latn-CM", + "bvn": "bvn-Latn-PG", + "bvo": "bvo-Latn-TD", + "bvq": "bvq-Latn-CF", + "bvr": "bvr-Latn-AU", + "bvt": "bvt-Latn-ID", + "bvu": "bvu-Latn-ID", + "bvv": "bvv-Latn-VE", + "bvw": "bvw-Latn-NG", + "bvx": "bvx-Latn-CG", + "bvy": "bvy-Latn-PH", + "bvz": "bvz-Latn-ID", + "bwa": "bwa-Latn-NC", + "bwb": "bwb-Latn-FJ", + "bwc": "bwc-Latn-ZM", + "bwd": "bwd-Latn-ZZ", + "bwe": "bwe-Mymr-MM", + "bwe-Latn": "bwe-Latn-MM", + "bwf": "bwf-Latn-PG", + "bwg": "bwg-Latn-MZ", + "bwh": "bwh-Latn-CM", + "bwi": "bwi-Latn-VE", + "bwj": "bwj-Latn-BF", + "bwk": "bwk-Latn-PG", + "bwl": "bwl-Latn-CD", + "bwm": "bwm-Latn-PG", + "bwo": "bwo-Latn-ET", + "bwo-Ethi": "bwo-Ethi-ET", + "bwp": "bwp-Latn-ID", + "bwq": "bwq-Latn-BF", + "bwr": "bwr-Latn-ZZ", + "bws": "bws-Latn-CD", + "bwt": "bwt-Latn-CM", + "bwu": "bwu-Latn-GH", + "bww": "bww-Latn-CD", + "bwx": "bwx-Latn-CN", + "bwy": "bwy-Latn-BF", + "bwz": "bwz-Latn-CG", + "bxa": "bxa-Latn-SB", + "bxb": "bxb-Latn-SS", + "bxc": "bxc-Latn-GQ", + "bxf": "bxf-Latn-PG", + "bxg": "bxg-Latn-CD", + "bxh": "bxh-Latn-ZZ", + "bxi": "bxi-Latn-AU", + "bxj": "bxj-Latn-AU", + "bxl": "bxl-Latn-BF", + "bxm": "bxm-Cyrl-MN", + "bxm-Latn": "bxm-Latn-MN", + "bxm-Mong": "bxm-Mong-MN", + "bxn": "bxn-Latn-AU", + "bxo": "bxo-Latn-NG", + "bxp": "bxp-Latn-CM", + "bxq": "bxq-Latn-NG", + "bxs": "bxs-Latn-CM", + "bxu": "bxu-Mong-CN", + "bxu-Cyrl": "bxu-Cyrl-CN", + "bxu-Latn": "bxu-Latn-CN", + "bxv": "bxv-Latn-TD", + "bxw": "bxw-Latn-ML", + "bxz": "bxz-Latn-PG", + "bya": "bya-Latn-PH", + "byb": "byb-Latn-CM", + "byc": "byc-Latn-NG", + "byd": "byd-Latn-ID", + "bye": "bye-Latn-ZZ", + "byf": "byf-Latn-NG", + "byh": "byh-Deva-NP", + "byi": "byi-Latn-CD", + "byj": "byj-Latn-NG", + "byk": "byk-Latn-CN", + "byl": "byl-Latn-ID", + "bym": "bym-Latn-AU", + "byn": "byn-Ethi-ER", + "byp": "byp-Latn-NG", + "byr": "byr-Latn-ZZ", + "bys": "bys-Latn-ZZ", + "byv": "byv-Latn-CM", + "byw": "byw-Deva-NP", + "byx": "byx-Latn-ZZ", + "byz": "byz-Latn-PG", + "bza": "bza-Latn-ZZ", + "bzb": "bzb-Latn-ID", + "bzc": "bzc-Latn-MG", + "bzd": "bzd-Latn-CR", + "bze": "bze-Latn-ML", + "bzf": "bzf-Latn-ZZ", + "bzh": "bzh-Latn-ZZ", + "bzi": "bzi-Thai-TH", + "bzj": "bzj-Latn-BZ", + "bzk": "bzk-Latn-NI", + "bzl": "bzl-Latn-ID", + "bzm": "bzm-Latn-CD", + "bzn": "bzn-Latn-ID", + "bzo": "bzo-Latn-CD", + "bzp": "bzp-Latn-ID", + "bzq": "bzq-Latn-ID", + "bzr": "bzr-Latn-AU", + "bzt": "bzt-Latn-001", + "bzu": "bzu-Latn-ID", + "bzv": "bzv-Latn-CM", + "bzw": "bzw-Latn-ZZ", + "bzx": "bzx-Latn-ML", + "bzy": "bzy-Latn-NG", + "bzz": "bzz-Latn-NG", + "ca": "ca-Latn-ES", + "caa": "caa-Latn-GT", + "cab": "cab-Latn-HN", + "cac": "cac-Latn-GT", + "cad": "cad-Latn-US", + "cae": "cae-Latn-SN", + "caf": "caf-Latn-CA", + "caf-Cans": "caf-Cans-CA", + "cag": "cag-Latn-PY", + "cah": "cah-Latn-PE", + "caj": "caj-Latn-AR", + "cak": "cak-Latn-GT", + "cal": "cal-Latn-MP", + "cam": "cam-Latn-NC", + "can": "can-Latn-ZZ", + "cao": "cao-Latn-BO", + "cap": "cap-Latn-BO", + "caq": "caq-Latn-IN", + "car": "car-Latn-VE", + "cas": "cas-Latn-BO", + "cav": "cav-Latn-BO", + "caw": "caw-Latn-BO", + "cax": "cax-Latn-BO", + "cay": "cay-Latn-CA", + "caz": "caz-Latn-BO", + "cbb": "cbb-Latn-CO", + "cbc": "cbc-Latn-CO", + "cbd": "cbd-Latn-CO", + "cbg": "cbg-Latn-CO", + "cbi": "cbi-Latn-EC", + "cbj": "cbj-Latn-ZZ", + "cbk": "cbk-Latn-PH", + "cbk-Brai": "cbk-Brai-PH", + "cbl": "cbl-Latn-MM", + "cbn": "cbn-Thai-TH", + "cbo": "cbo-Latn-NG", + "cbq": "cbq-Latn-NG", + "cbr": "cbr-Latn-PE", + "cbs": "cbs-Latn-PE", + "cbt": "cbt-Latn-PE", + "cbu": "cbu-Latn-PE", + "cbv": "cbv-Latn-CO", + "cbw": "cbw-Latn-PH", + "cby": "cby-Latn-CO", + "ccc": "ccc-Latn-PE", + "ccd": "ccd-Latn-BR", + "cce": "cce-Latn-MZ", + "ccg": "ccg-Latn-NG", + "cch": "cch-Latn-NG", + "ccj": "ccj-Latn-GW", + "ccl": "ccl-Latn-TZ", + "ccm": "ccm-Latn-MY", + "cco": "cco-Latn-MX", + "ccp": "ccp-Cakm-BD", + "ccr": "ccr-Latn-SV", + "cde": "cde-Telu-IN", + "cdf": "cdf-Latn-IN", + "cdf-Beng": "cdf-Beng-IN", + "cdh": "cdh-Deva-IN", + "cdh-Takr": "cdh-Takr-IN", + "cdi": "cdi-Gujr-IN", + "cdj": "cdj-Deva-IN", + "cdm": "cdm-Deva-NP", + "cdm-Latn": "cdm-Latn-NP", + "cdo": "cdo-Hans-CN", + "cdo-Hant": "cdo-Hant-CN", + "cdo-Latn": "cdo-Latn-CN", + "cdr": "cdr-Latn-NG", + "cdz": "cdz-Beng-IN", + "ce": "ce-Cyrl-RU", + "cea": "cea-Latn-US", + "ceb": "ceb-Latn-PH", + "ceg": "ceg-Latn-PY", + "cek": "cek-Latn-MM", + "cen": "cen-Latn-NG", + "cet": "cet-Latn-NG", + "cey": "cey-Latn-MM", + "cfa": "cfa-Latn-ZZ", + "cfd": "cfd-Latn-NG", + "cfg": "cfg-Latn-NG", + "cfm": "cfm-Latn-MM", + "cfm-Beng": "cfm-Beng-IN", + "cga": "cga-Latn-PG", + "cgc": "cgc-Latn-PH", + "cgg": "cgg-Latn-UG", + "cgk": "cgk-Tibt-BT", + "ch": "ch-Latn-GU", + "chb": "chb-Latn-CO", + "chd": "chd-Latn-MX", + "chf": "chf-Latn-MX", + "chg": "chg-Arab-TM", + "chh": "chh-Latn-US", + "chj": "chj-Latn-MX", + "chk": "chk-Latn-FM", + "chl": "chl-Latn-US", + "chm": "chm-Cyrl-RU", + "chn": "chn-Latn-US", + "chn-Dupl": "chn-Dupl-US", + "cho": "cho-Latn-US", + "chp": "chp-Latn-CA", + "chq": "chq-Latn-MX", + "chr": "chr-Cher-US", + "cht": "cht-Latn-PE", + "chw": "chw-Latn-MZ", + "chx": "chx-Deva-NP", + "chy": "chy-Latn-US", + "chz": "chz-Latn-MX", + "cia": "cia-Latn-ID", + "cia-Arab": "cia-Arab-ID", + "cia-Hang": "cia-Hang-ID", + "cib": "cib-Latn-BJ", + "cic": "cic-Latn-US", + "cie": "cie-Latn-NG", + "cih": "cih-Deva-IN", + "cim": "cim-Latn-IT", + "cin": "cin-Latn-BR", + "cip": "cip-Latn-MX", + "cir": "cir-Latn-NC", + "ciw": "ciw-Latn-US", + "ciw-Cans": "ciw-Cans-US", + "ciy": "ciy-Latn-VE", + "cja": "cja-Arab-KH", + "cje": "cje-Latn-VN", + "cjh": "cjh-Latn-US", + "cji": "cji-Cyrl-RU", + "cjk": "cjk-Latn-AO", + "cjm": "cjm-Cham-VN", + "cjn": "cjn-Latn-PG", + "cjo": "cjo-Latn-PE", + "cjp": "cjp-Latn-CR", + "cjs": "cjs-Latn-RU", + "cjs-Cyrl": "cjs-Cyrl-RU", + "cjv": "cjv-Latn-ZZ", + "cjy": "cjy-Hans-CN", + "cjy-Hant": "cjy-Hant-CN", + "ckb": "ckb-Arab-IQ", + "ckl": "ckl-Latn-ZZ", + "ckm": "ckm-Latn-HR", + "ckm-Glag": "ckm-Glag-HR", + "ckn": "ckn-Latn-MM", + "cko": "cko-Latn-ZZ", + "ckq": "ckq-Latn-TD", + "ckr": "ckr-Latn-PG", + "cks": "cks-Latn-NC", + "ckt": "ckt-Cyrl-RU", + "cku": "cku-Latn-US", + "ckv": "ckv-Latn-TW", + "ckx": "ckx-Latn-CM", + "cky": "cky-Latn-ZZ", + "ckz": "ckz-Latn-GT", + "cla": "cla-Latn-ZZ", + "clc": "clc-Latn-CA", + "cle": "cle-Latn-MX", + "clh": "clh-Arab-PK", + "cli": "cli-Latn-GH", + "clj": "clj-Latn-MM", + "clk": "clk-Latn-IN", + "clk-Tibt": "clk-Tibt-CN", + "cll": "cll-Latn-GH", + "clm": "clm-Latn-US", + "clo": "clo-Latn-MX", + "clt": "clt-Latn-MM", + "clu": "clu-Latn-PH", + "clw": "clw-Cyrl-RU", + "cly": "cly-Latn-MX", + "cma": "cma-Latn-VN", + "cme": "cme-Latn-ZZ", + "cmg": "cmg-Soyo-MN", + "cmi": "cmi-Latn-CO", + "cml": "cml-Latn-ID", + "cmo": "cmo-Latn-VN", + "cmo-KH": "cmo-Latn-KH", + "cmo-Khmr": "cmo-Khmr-KH", + "cmr": "cmr-Latn-MM", + "cms": "cms-Latn-IT", + "cmt": "cmt-Latn-ZA", + "cna": "cna-Tibt-IN", + "cnb": "cnb-Latn-MM", + "cnc": "cnc-Latn-VN", + "cng": "cng-Latn-CN", + "cnh": "cnh-Latn-MM", + "cni": "cni-Latn-PE", + "cnk": "cnk-Latn-MM", + "cnl": "cnl-Latn-MX", + "cnp": "cnp-Hans-CN", + "cnp-Hant": "cnp-Hant-CN", + "cnq": "cnq-Latn-CM", + "cns": "cns-Latn-ID", + "cnt": "cnt-Latn-MX", + "cnw": "cnw-Latn-MM", + "cnx": "cnx-Latn-GB", + "co": "co-Latn-FR", + "coa": "coa-Latn-AU", + "cob": "cob-Latn-MX", + "coc": "coc-Latn-MX", + "cod": "cod-Latn-PE", + "coe": "coe-Latn-CO", + "cof": "cof-Latn-EC", + "cog": "cog-Thai-TH", + "coh": "coh-Latn-KE", + "coj": "coj-Latn-MX", + "cok": "cok-Latn-MX", + "col": "col-Latn-US", + "com": "com-Latn-US", + "coo": "coo-Latn-CA", + "cop": "cop-Copt-EG", + "coq": "coq-Latn-US", + "cot": "cot-Latn-PE", + "cou": "cou-Latn-SN", + "cox": "cox-Latn-PE", + "coz": "coz-Latn-MX", + "cpa": "cpa-Latn-MX", + "cpb": "cpb-Latn-PE", + "cpc": "cpc-Latn-PE", + "cpg": "cpg-Grek-GR", + "cpi": "cpi-Latn-NR", + "cpn": "cpn-Latn-GH", + "cpo": "cpo-Latn-BF", + "cps": "cps-Latn-PH", + "cpu": "cpu-Latn-PE", + "cpx": "cpx-Latn-CN", + "cpy": "cpy-Latn-PE", + "cqd": "cqd-Latn-CN", + "cr": "cr-Cans-CA", + "crb": "crb-Latn-VC", + "crc": "crc-Latn-VU", + "crd": "crd-Latn-US", + "crf": "crf-Latn-CO", + "crg": "crg-Latn-CA", + "crh": "crh-Cyrl-UA", + "cri": "cri-Latn-ST", + "crj": "crj-Cans-CA", + "crj-Latn": "crj-Latn-CA", + "crk": "crk-Cans-CA", + "crl": "crl-Cans-CA", + "crm": "crm-Cans-CA", + "crn": "crn-Latn-MX", + "cro": "cro-Latn-US", + "crq": "crq-Latn-AR", + "crs": "crs-Latn-SC", + "crt": "crt-Latn-AR", + "crv": "crv-Latn-IN", + "crw": "crw-Latn-VN", + "crx": "crx-Latn-CA", + "crx-Cans": "crx-Cans-CA", + "cry": "cry-Latn-NG", + "crz": "crz-Latn-US", + "cs": "cs-Latn-CZ", + "csa": "csa-Latn-MX", + "csb": "csb-Latn-PL", + "csh": "csh-Mymr-MM", + "csh-Latn": "csh-Latn-MM", + "csj": "csj-Latn-MM", + "csk": "csk-Latn-SN", + "csm": "csm-Latn-US", + "cso": "cso-Latn-MX", + "csp": "csp-Hans-CN", + "csp-Hant": "csp-Hant-CN", + "css": "css-Latn-US", + "cst": "cst-Latn-US", + "csv": "csv-Latn-MM", + "csw": "csw-Cans-CA", + "csy": "csy-Latn-MM", + "csz": "csz-Latn-US", + "cta": "cta-Latn-MX", + "ctc": "ctc-Latn-US", + "ctd": "ctd-Pauc-MM", + "cte": "cte-Latn-MX", + "ctg": "ctg-Beng-BD", + "ctg-Arab": "ctg-Arab-BD", + "ctg-Latn": "ctg-Latn-BD", + "cth": "cth-Latn-MM", + "ctl": "ctl-Latn-MX", + "ctm": "ctm-Latn-US", + "ctn": "ctn-Deva-NP", + "cto": "cto-Latn-CO", + "ctp": "ctp-Latn-MX", + "cts": "cts-Latn-PH", + "ctt": "ctt-Taml-IN", + "ctu": "ctu-Latn-MX", + "ctz": "ctz-Latn-MX", + "cu": "cu-Cyrl-RU", + "cu-Glag": "cu-Glag-BG", + "cua": "cua-Latn-VN", + "cub": "cub-Latn-CO", + "cuc": "cuc-Latn-MX", + "cuh": "cuh-Latn-KE", + "cui": "cui-Latn-CO", + "cuj": "cuj-Latn-PE", + "cuk": "cuk-Latn-PA", + "cul": "cul-Latn-BR", + "cuo": "cuo-Latn-VE", + "cup": "cup-Latn-US", + "cut": "cut-Latn-MX", + "cuu": "cuu-Lana-CN", + "cuv": "cuv-Latn-CM", + "cux": "cux-Latn-MX", + "cv": "cv-Cyrl-RU", + "cvg": "cvg-Latn-IN", + "cvg-Tibt": "cvg-Tibt-IN", + "cvn": "cvn-Latn-MX", + "cwa": "cwa-Latn-TZ", + "cwb": "cwb-Latn-MZ", + "cwe": "cwe-Latn-TZ", + "cwg": "cwg-Latn-MY", + "cwt": "cwt-Latn-SN", + "cy": "cy-Latn-GB", + "cya": "cya-Latn-MX", + "cyb": "cyb-Latn-BO", + "cyo": "cyo-Latn-PH", + "czh": "czh-Hans-CN", + "czh-Hant": "czh-Hant-CN", + "czk": "czk-Hebr-CZ", + "czn": "czn-Latn-MX", + "czt": "czt-Latn-MM", + "da": "da-Latn-DK", + "daa": "daa-Latn-TD", + "dac": "dac-Latn-PG", + "dad": "dad-Latn-ZZ", + "dae": "dae-Latn-CM", + "daf": "dnj-Latn-CI", + "dag": "dag-Latn-ZZ", + "dah": "dah-Latn-ZZ", + "dai": "dai-Latn-TD", + "daj": "daj-Latn-SD", + "dak": "dak-Latn-US", + "dal": "dal-Latn-KE", + "dam": "dam-Latn-NG", + "dao": "dao-Latn-MM", + "daq": "daq-Deva-IN", + "dar": "dar-Cyrl-RU", + "das": "das-Latn-CI", + "dau": "dau-Latn-TD", + "dav": "dav-Latn-KE", + "daw": "daw-Latn-PH", + "dax": "dax-Latn-AU", + "daz": "daz-Latn-ID", + "dba": "dba-Latn-ML", + "dbb": "dbb-Latn-NG", + "dbd": "dbd-Latn-ZZ", + "dbe": "dbe-Latn-ID", + "dbf": "dbf-Latn-ID", + "dbg": "dbg-Latn-ML", + "dbi": "dbi-Latn-NG", + "dbj": "dbj-Latn-MY", + "dbj-Arab": "dbj-Arab-MY", + "dbl": "dbl-Latn-AU", + "dbm": "dbm-Latn-NG", + "dbn": "dbn-Latn-ID", + "dbo": "dbo-Latn-NG", + "dbp": "dbp-Latn-NG", + "dbq": "dbq-Latn-ZZ", + "dbt": "dbt-Latn-ML", + "dbu": "dbu-Latn-ML", + "dbv": "dbv-Latn-NG", + "dbw": "dbw-Latn-ML", + "dby": "dby-Latn-PG", + "dcc": "dcc-Arab-IN", + "dcr": "dcr-Latn-VI", + "dda": "dda-Latn-AU", + "ddd": "ddd-Latn-SS", + "dde": "dde-Latn-CG", + "ddg": "ddg-Latn-TL", + "ddi": "ddi-Latn-PG", + "ddj": "ddj-Latn-AU", + "ddn": "ddn-Latn-ZZ", + "ddo": "ddo-Cyrl-RU", + "ddr": "ddr-Latn-AU", + "dds": "dds-Latn-ML", + "ddw": "ddw-Latn-ID", + "de": "de-Latn-DE", + "dec": "dec-Latn-SD", + "ded": "ded-Latn-ZZ", + "dee": "dee-Latn-LR", + "def": "def-Arab-IR", + "deg": "deg-Latn-NG", + "deh": "deh-Arab-PK", + "dei": "dei-Latn-ID", + "dek": "dek-Latn-CM", + "del": "del-Latn-US", + "dem": "dem-Latn-ID", + "den": "den-Latn-CA", + "deq": "deq-Latn-CF", + "der": "der-Beng-IN", + "der-Latn": "der-Latn-IN", + "des": "des-Latn-BR", + "dev": "dev-Latn-PG", + "dez": "dez-Latn-CD", + "dga": "dga-Latn-ZZ", + "dgb": "dgb-Latn-ML", + "dgc": "dgc-Latn-PH", + "dgd": "dgd-Latn-BF", + "dge": "dge-Latn-PG", + "dgg": "dgg-Latn-PG", + "dgh": "dgh-Latn-ZZ", + "dgi": "dgi-Latn-ZZ", + "dgk": "dgk-Latn-CF", + "dgl": "dgl-Arab-ZZ", + "dgn": "dgn-Latn-AU", + "dgr": "dgr-Latn-CA", + "dgs": "dgs-Latn-BF", + "dgt": "dgt-Latn-AU", + "dgw": "dgw-Latn-AU", + "dgx": "dgx-Latn-PG", + "dgz": "dgz-Latn-ZZ", + "dhg": "dhg-Latn-AU", + "dhi": "dhi-Deva-NP", + "dhl": "dhl-Latn-AU", + "dhm": "dhm-Latn-AO", + "dhn": "dhn-Gujr-IN", + "dho": "dho-Deva-IN", + "dhr": "dhr-Latn-AU", + "dhs": "dhs-Latn-TZ", + "dhu": "dhu-Latn-AU", + "dhv": "dhv-Latn-NC", + "dhw": "dhw-Deva-NP", + "dhx": "dhx-Latn-AU", + "dia": "dia-Latn-ZZ", + "dib": "dib-Latn-SS", + "dic": "dic-Latn-CI", + "did": "did-Latn-SS", + "dif": "dif-Latn-AU", + "dig": "dig-Latn-KE", + "dih": "dih-Latn-MX", + "dii": "dii-Latn-CM", + "dij": "dij-Latn-ID", + "dil": "dil-Latn-SD", + "din": "din-Latn-SS", + "din-Arab": "din-Arab-SS", + "dio": "dio-Latn-NG", + "dip": "dip-Latn-SS", + "dir": "dir-Latn-NG", + "dis": "dis-Latn-IN", + "dis-Beng": "dis-Beng-IN", + "diu": "diu-Latn-NA", + "diw": "diw-Latn-SS", + "dix": "dix-Latn-VU", + "diy": "diy-Latn-ID", + "diz": "diz-Latn-CD", + "dja": "dja-Latn-AU", + "djb": "djb-Latn-AU", + "djc": "djc-Latn-TD", + "djd": "djd-Latn-AU", + "dje": "dje-Latn-NE", + "djf": "djf-Latn-AU", + "dji": "dji-Latn-AU", + "djj": "djj-Latn-AU", + "djk": "djk-Latn-SR", + "djm": "djm-Latn-ML", + "djn": "djn-Latn-AU", + "djo": "djo-Latn-ID", + "djr": "djr-Latn-AU", + "dju": "dju-Latn-PG", + "djw": "djw-Latn-AU", + "dka": "dka-Tibt-BT", + "dkg": "dkg-Latn-NG", + "dkk": "dkk-Latn-ID", + "dkr": "dkr-Latn-MY", + "dks": "dks-Latn-SS", + "dkx": "dkx-Latn-CM", + "dlg": "dlg-Cyrl-RU", + "dlm": "dlm-Latn-HR", + "dln": "dln-Latn-IN", + "dma": "dma-Latn-GA", + "dmb": "dmb-Latn-ML", + "dmc": "dmc-Latn-PG", + "dmd": "dmd-Latn-AU", + "dme": "dme-Latn-CM", + "dmf": "dmf-Medf-NG", + "dmg": "dmg-Latn-MY", + "dmk": "dmk-Arab-PK", + "dml": "dml-Arab-PK", + "dmm": "dmm-Latn-CM", + "dmo": "dmo-Latn-CM", + "dmr": "dmr-Latn-ID", + "dms": "dms-Latn-ID", + "dmu": "dmu-Latn-ID", + "dmv": "dmv-Latn-MY", + "dmw": "dmw-Latn-AU", + "dmx": "dmx-Latn-MZ", + "dmy": "dmy-Latn-ID", + "dna": "dna-Latn-ID", + "dnd": "dnd-Latn-PG", + "dne": "dne-Latn-TZ", + "dng": "dng-Cyrl-KG", + "dng-Arab": "dng-Arab-KG", + "dni": "dni-Latn-ID", + "dnj": "dnj-Latn-CI", + "dnk": "dnk-Latn-ID", + "dnn": "dnn-Latn-BF", + "dno": "dno-Latn-CD", + "dnr": "dnr-Latn-PG", + "dnt": "dnt-Latn-ID", + "dnu": "dnu-Mymr-MM", + "dnv": "dnv-Mymr-MM", + "dnw": "dnw-Latn-ID", + "dny": "dny-Latn-BR", + "doa": "doa-Latn-PG", + "dob": "dob-Latn-ZZ", + "doc": "doc-Latn-CN", + "doe": "doe-Latn-TZ", + "dof": "dof-Latn-PG", + "doh": "doh-Latn-NG", + "doi": "doi-Deva-IN", + "dok": "dok-Latn-ID", + "dol": "dol-Latn-PG", + "don": "don-Latn-PG", + "doo": "doo-Latn-CD", + "dop": "dop-Latn-ZZ", + "dor": "dor-Latn-SB", + "dos": "dos-Latn-BF", + "dot": "dot-Latn-NG", + "dov": "dov-Latn-ZW", + "dow": "dow-Latn-ZZ", + "dox": "dox-Ethi-ET", + "doy": "doy-Latn-GH", + "dpp": "dpp-Latn-MY", + "drc": "drc-Latn-PT", + "dre": "dre-Tibt-NP", + "drg": "drg-Latn-MY", + "drh": "mn-Cyrl-MN", + "dri": "dri-Latn-ZZ", + "drl": "drl-Latn-AU", + "drn": "drn-Latn-ID", + "dro": "dro-Latn-MY", + "drq": "drq-Deva-NP", + "drs": "drs-Ethi-ZZ", + "drt": "drt-Latn-NL", + "dru": "dru-Latn-TW", + "dry": "dry-Deva-NP", + "dsb": "dsb-Latn-DE", + "dsh": "dsh-Latn-KE", + "dsi": "dsi-Latn-TD", + "dsn": "dsn-Latn-ID", + "dso": "dso-Orya-IN", + "dsq": "dsq-Latn-ML", + "dsq-Arab": "dsq-Arab-ML", + "dta": "dta-Latn-CN", + "dta-Cyrl": "dta-Cyrl-CN", + "dta-Hans": "dta-Hans-CN", + "dtb": "dtb-Latn-MY", + "dtd": "dtd-Latn-CA", + "dth": "dth-Latn-AU", + "dti": "dti-Latn-ML", + "dtk": "dtk-Latn-ML", + "dtm": "dtm-Latn-ML", + "dto": "dto-Latn-ML", + "dtp": "dtp-Latn-MY", + "dtr": "dtr-Latn-MY", + "dts": "dts-Latn-ZZ", + "dtt": "dtt-Latn-ML", + "dtu": "dtu-Latn-ML", + "dty": "dty-Deva-NP", + "dua": "dua-Latn-CM", + "dub": "dub-Gujr-IN", + "duc": "duc-Latn-ZZ", + "dud": "uth-Latn-ZZ", + "due": "due-Latn-PH", + "duf": "duf-Latn-NC", + "dug": "dug-Latn-ZZ", + "duh": "duh-Deva-IN", + "duh-Gujr": "duh-Gujr-IN", + "dui": "dui-Latn-PG", + "duk": "duk-Latn-PG", + "dul": "dul-Latn-PH", + "dum": "dum-Latn-NL", + "dun": "dun-Latn-ID", + "duo": "duo-Latn-PH", + "dup": "dup-Latn-ID", + "duq": "duq-Latn-ID", + "dur": "dur-Latn-CM", + "dus": "dus-Deva-NP", + "duu": "duu-Latn-CN", + "duv": "duv-Latn-ID", + "duw": "duw-Latn-ID", + "dux": "dux-Latn-ML", + "duy": "duy-Latn-PH", + "duz": "duz-Latn-CM", + "dv": "dv-Thaa-MV", + "dva": "dva-Latn-ZZ", + "dwa": "dwa-Latn-NG", + "dwk": "dwk-Orya-IN", + "dwr": "dwr-Latn-ET", + "dwr-Ethi": "dwr-Ethi-ET", + "dws": "dws-Latn-001", + "dwu": "dwu-Latn-AU", + "dww": "dww-Latn-ZZ", + "dwy": "dwy-Latn-AU", + "dwz": "dwz-Deva-NP", + "dya": "dya-Latn-BF", + "dyb": "dyb-Latn-AU", + "dyd": "dyd-Latn-AU", + "dyg": "dyg-Latn-PH", + "dyi": "dyi-Latn-CI", + "dym": "dym-Latn-ML", + "dyn": "dyn-Latn-AU", + "dyo": "dyo-Latn-SN", + "dyu": "dyu-Latn-BF", + "dyy": "dyy-Latn-AU", + "dz": "dz-Tibt-BT", + "dza": "dza-Latn-NG", + "dze": "dze-Latn-AU", + "dzg": "dzg-Latn-ZZ", + "dzl": "dzl-Tibt-BT", + "dzn": "dzn-Latn-CD", + "eaa": "eaa-Latn-AU", + "ebc": "ebc-Latn-ID", + "ebg": "ebg-Latn-NG", + "ebk": "ebk-Latn-PH", + "ebo": "ebo-Latn-CG", + "ebr": "ebr-Latn-CI", + "ebu": "ebu-Latn-KE", + "ecr": "ecr-Grek-GR", + "ecy": "ecy-Cprt-CY", + "ee": "ee-Latn-GH", + "efa": "efa-Latn-NG", + "efe": "efe-Latn-CD", + "efi": "efi-Latn-NG", + "ega": "ega-Latn-CI", + "egl": "egl-Latn-IT", + "egm": "egm-Latn-TZ", + "ego": "ego-Latn-NG", + "egy": "egy-Egyp-EG", + "ehu": "ehu-Latn-NG", + "eip": "eip-Latn-ID", + "eit": "eit-Latn-PG", + "eiv": "eiv-Latn-PG", + "eja": "eja-Latn-GW", + "eka": "eka-Latn-ZZ", + "eke": "eke-Latn-NG", + "ekg": "ekg-Latn-ID", + "eki": "eki-Latn-NG", + "ekl": "ekl-Latn-BD", + "ekm": "ekm-Latn-CM", + "eko": "eko-Latn-MZ", + "eko-Arab": "eko-Arab-MZ", + "ekp": "ekp-Latn-NG", + "ekr": "ekr-Latn-NG", + "eky": "eky-Kali-MM", + "el": "el-Grek-GR", + "ele": "ele-Latn-PG", + "elk": "elk-Latn-PG", + "elm": "elm-Latn-NG", + "elo": "elo-Latn-KE", + "elu": "elu-Latn-PG", + "ema": "ema-Latn-ZZ", + "emb": "emb-Latn-ID", + "eme": "eme-Latn-GF", + "emg": "emg-Deva-NP", + "emi": "emi-Latn-ZZ", + "emm": "emm-Latn-MX", + "emn": "emn-Latn-CM", + "emp": "emp-Latn-PA", + "ems": "ems-Latn-US", + "ems-Cyrl": "ems-Cyrl-US", + "emu": "emu-Deva-IN", + "emw": "emw-Latn-ID", + "emx": "emx-Latn-FR", + "emz": "emz-Latn-CM", + "en": "en-Latn-US", + "en-Shaw": "en-Shaw-GB", + "ena": "ena-Latn-PG", + "enb": "enb-Latn-KE", + "enc": "enc-Latn-VN", + "end": "end-Latn-ID", + "enf": "enf-Cyrl-RU", + "enh": "enh-Cyrl-RU", + "enl": "enl-Latn-PY", + "enm": "enm-Latn-GB", + "enn": "enn-Latn-ZZ", + "eno": "eno-Latn-ID", + "enq": "enq-Latn-ZZ", + "enr": "enr-Latn-ID", + "env": "env-Latn-NG", + "enw": "enw-Latn-NG", + "enx": "enx-Latn-PY", + "eo": "eo-Latn-001", + "eot": "eot-Latn-CI", + "epi": "epi-Latn-NG", + "era": "era-Taml-IN", + "erg": "erg-Latn-VU", + "erh": "erh-Latn-NG", + "eri": "eri-Latn-ZZ", + "erk": "erk-Latn-VU", + "err": "err-Latn-AU", + "ert": "ert-Latn-ID", + "erw": "erw-Latn-ID", + "es": "es-Latn-ES", + "ese": "ese-Latn-BO", + "esg": "esg-Gonm-IN", + "esh": "esh-Arab-IR", + "esi": "esi-Latn-US", + "esm": "esm-Latn-CI", + "ess": "ess-Latn-US", + "ess-Cyrl": "ess-Cyrl-US", + "esu": "esu-Latn-US", + "esy": "esy-Latn-PH", + "et": "et-Latn-EE", + "etb": "etb-Latn-NG", + "etn": "etn-Latn-VU", + "eto": "eto-Latn-CM", + "etr": "etr-Latn-ZZ", + "ets": "ets-Latn-NG", + "ett": "ett-Ital-IT", + "etu": "etu-Latn-ZZ", + "etx": "etx-Latn-ZZ", + "etz": "etz-Latn-ID", + "eu": "eu-Latn-ES", + "eve": "eve-Cyrl-RU", + "evh": "evh-Latn-NG", + "evn": "evn-Cyrl-RU", + "evn-Latn": "evn-Latn-CN", + "evn-Mong": "evn-Mong-CN", + "ewo": "ewo-Latn-CM", + "ext": "ext-Latn-ES", + "eya": "eya-Latn-US", + "eyo": "eyo-Latn-KE", + "eza": "eza-Latn-ZZ", + "eze": "eze-Latn-NG", + "fa": "fa-Arab-IR", + "faa": "faa-Latn-ZZ", + "fab": "fab-Latn-ZZ", + "fad": "fad-Latn-PG", + "faf": "faf-Latn-SB", + "fag": "fag-Latn-ZZ", + "fah": "fah-Latn-NG", + "fai": "fai-Latn-ZZ", + "faj": "faj-Latn-PG", + "fak": "fak-Latn-CM", + "fal": "fal-Latn-CM", + "fam": "fam-Latn-NG", + "fan": "fan-Latn-GQ", + "fap": "fap-Latn-SN", + "far": "far-Latn-SB", + "fau": "fau-Latn-ID", + "fax": "fax-Latn-ES", + "fay": "fay-Arab-IR", + "faz": "faz-Arab-IR", + "fbl": "fbl-Latn-PH", + "fer": "fer-Latn-SS", + "ff": "ff-Latn-SN", + "ff-Adlm": "ff-Adlm-GN", + "ffi": "ffi-Latn-ZZ", + "ffm": "ffm-Latn-ML", + "fgr": "fgr-Latn-TD", + "fi": "fi-Latn-FI", + "fia": "fia-Arab-SD", + "fie": "fie-Latn-NG", + "fif": "fif-Latn-SA", + "fil": "fil-Latn-PH", + "fip": "fip-Latn-TZ", + "fir": "fir-Latn-NG", + "fit": "fit-Latn-SE", + "fiw": "fiw-Latn-PG", + "fj": "fj-Latn-FJ", + "fkk": "fkk-Latn-NG", + "fkv": "fkv-Latn-NO", + "fla": "fla-Latn-US", + "flh": "flh-Latn-ID", + "fli": "fli-Latn-NG", + "fll": "fll-Latn-CM", + "fln": "fln-Latn-AU", + "flr": "flr-Latn-ZZ", + "fly": "fly-Latn-ZA", + "fmp": "fmp-Latn-ZZ", + "fmu": "fmu-Deva-IN", + "fnb": "fnb-Latn-VU", + "fng": "fng-Latn-ZA", + "fni": "fni-Latn-TD", + "fo": "fo-Latn-FO", + "fod": "fod-Latn-ZZ", + "foi": "foi-Latn-PG", + "fom": "fom-Latn-CD", + "fon": "fon-Latn-BJ", + "for": "for-Latn-ZZ", + "fos": "fos-Latn-TW", + "fpe": "fpe-Latn-ZZ", + "fqs": "fqs-Latn-ZZ", + "fr": "fr-Latn-FR", + "frc": "frc-Latn-US", + "frd": "frd-Latn-ID", + "frk": "frk-Latn-DE", + "frm": "frm-Latn-FR", + "fro": "fro-Latn-FR", + "frp": "frp-Latn-FR", + "frq": "frq-Latn-PG", + "frr": "frr-Latn-DE", + "frs": "frs-Latn-DE", + "frt": "frt-Latn-VU", + "fub": "fub-Arab-CM", + "fud": "fud-Latn-WF", + "fue": "fue-Latn-ZZ", + "fuf": "fuf-Latn-GN", + "fuh": "fuh-Latn-ZZ", + "fui": "fui-Latn-TD", + "fum": "fum-Latn-NG", + "fun": "fun-Latn-BR", + "fuq": "fuq-Latn-NE", + "fur": "fur-Latn-IT", + "fut": "fut-Latn-VU", + "fuu": "fuu-Latn-CD", + "fuv": "fuv-Latn-NG", + "fuy": "fuy-Latn-ZZ", + "fvr": "fvr-Latn-SD", + "fwa": "fwa-Latn-NC", + "fwe": "fwe-Latn-NA", + "fy": "fy-Latn-NL", + "ga": "ga-Latn-IE", + "gaa": "gaa-Latn-GH", + "gab": "gab-Latn-TD", + "gac": "gac-Latn-IN", + "gac-Deva": "gac-Deva-IN", + "gad": "gad-Latn-PH", + "gae": "gae-Latn-VE", + "gaf": "gaf-Latn-ZZ", + "gag": "gag-Latn-MD", + "gah": "gah-Latn-ZZ", + "gai": "gai-Latn-PG", + "gaj": "gaj-Latn-ZZ", + "gak": "gak-Latn-ID", + "gal": "gal-Latn-TL", + "gam": "gam-Latn-ZZ", + "gan": "gan-Hans-CN", + "gao": "gao-Latn-PG", + "gap": "gap-Latn-PG", + "gaq": "gaq-Orya-IN", + "gar": "gar-Latn-PG", + "gas": "gas-Gujr-IN", + "gat": "gat-Latn-PG", + "gau": "gau-Telu-IN", + "gaw": "gaw-Latn-ZZ", + "gax": "gax-Latn-ET", + "gax-Ethi": "gax-Ethi-ET", + "gay": "gay-Latn-ID", + "gba": "gba-Latn-ZZ", + "gbb": "gbb-Latn-AU", + "gbd": "gbd-Latn-AU", + "gbe": "gbe-Latn-PG", + "gbf": "gbf-Latn-ZZ", + "gbg": "gbg-Latn-CF", + "gbh": "gbh-Latn-BJ", + "gbi": "gbi-Latn-ID", + "gbj": "gbj-Orya-IN", + "gbk": "gbk-Deva-IN", + "gbk-Takr": "gbk-Takr-IN", + "gbl": "gbl-Gujr-IN", + "gbl-Deva": "gbl-Deva-IN", + "gbm": "gbm-Deva-IN", + "gbn": "gbn-Latn-SS", + "gbp": "gbp-Latn-CF", + "gbq": "gbq-Latn-CF", + "gbr": "gbr-Latn-NG", + "gbs": "gbs-Latn-BJ", + "gbu": "gbu-Latn-AU", + "gbv": "gbv-Latn-CF", + "gbw": "gbw-Latn-AU", + "gbx": "gbx-Latn-BJ", + "gby": "gby-Latn-ZZ", + "gbz": "gbz-Arab-IR", + "gcc": "gcc-Latn-PG", + "gcd": "gcd-Latn-AU", + "gcf": "gcf-Latn-GP", + "gcl": "gcl-Latn-GD", + "gcn": "gcn-Latn-PG", + "gcr": "gcr-Latn-GF", + "gct": "gct-Latn-VE", + "gd": "gd-Latn-GB", + "gdb": "gdb-Orya-IN", + "gdb-Telu": "gdb-Telu-IN", + "gdc": "gdc-Latn-AU", + "gdd": "gdd-Latn-PG", + "gde": "gde-Latn-ZZ", + "gdf": "gdf-Latn-NG", + "gdg": "gdg-Latn-PH", + "gdh": "gdh-Latn-AU", + "gdi": "gdi-Latn-CF", + "gdj": "gdj-Latn-AU", + "gdk": "gdk-Latn-TD", + "gdl": "gdl-Latn-ET", + "gdl-Ethi": "gdl-Ethi-ET", + "gdm": "gdm-Latn-TD", + "gdn": "gdn-Latn-ZZ", + "gdo": "gdo-Cyrl-RU", + "gdq": "gdq-Latn-YE", + "gdr": "gdr-Latn-ZZ", + "gdt": "gdt-Latn-AU", + "gdu": "gdu-Latn-NG", + "gdx": "gdx-Deva-IN", + "gea": "gea-Latn-NG", + "geb": "geb-Latn-ZZ", + "gec": "gec-Latn-LR", + "ged": "ged-Latn-NG", + "gef": "gef-Latn-ID", + "geg": "geg-Latn-NG", + "geh": "geh-Latn-CA", + "gei": "gei-Latn-ID", + "gej": "gej-Latn-ZZ", + "gek": "gek-Latn-NG", + "gel": "gel-Latn-ZZ", + "geq": "geq-Latn-CF", + "ges": "ges-Latn-ID", + "gev": "gev-Latn-GA", + "gew": "gew-Latn-NG", + "gex": "gex-Latn-SO", + "gey": "gey-Latn-CD", + "gez": "gez-Ethi-ET", + "gfk": "gfk-Latn-ZZ", + "gga": "gga-Latn-SB", + "ggb": "ggb-Latn-LR", + "ggd": "ggd-Latn-AU", + "gge": "gge-Latn-AU", + "ggg": "ggg-Arab-PK", + "ggk": "ggk-Latn-AU", + "ggl": "ggl-Latn-PG", + "ggn": "gvr-Deva-NP", + "ggt": "ggt-Latn-PG", + "ggu": "ggu-Latn-CI", + "ggw": "ggw-Latn-PG", + "gha": "gha-Arab-LY", + "gha-Latn": "gha-Latn-LY", + "gha-Tfng": "gha-Tfng-LY", + "ghc": "ghc-Latn-GB", + "ghe": "ghe-Deva-NP", + "ghk": "ghk-Latn-MM", + "ghn": "ghn-Latn-SB", + "ghr": "ghr-Arab-PK", + "ghs": "ghs-Latn-ZZ", + "ght": "ght-Tibt-NP", + "gia": "gia-Latn-AU", + "gib": "gib-Latn-NG", + "gic": "gic-Latn-ZA", + "gid": "gid-Latn-CM", + "gie": "gie-Latn-CI", + "gig": "gig-Arab-PK", + "gih": "gih-Latn-AU", + "gil": "gil-Latn-KI", + "gim": "gim-Latn-ZZ", + "gin": "gin-Cyrl-RU", + "gip": "gip-Latn-PG", + "giq": "giq-Latn-VN", + "gir": "gir-Latn-VN", + "gis": "gis-Latn-CM", + "git": "git-Latn-CA", + "gix": "gix-Latn-CD", + "giy": "giy-Latn-AU", + "giz": "giz-Latn-CM", + "gjk": "gjk-Arab-PK", + "gjm": "gjm-Latn-AU", + "gjn": "gjn-Latn-ZZ", + "gjr": "gjr-Latn-AU", + "gju": "gju-Arab-PK", + "gka": "gka-Latn-PG", + "gkd": "gkd-Latn-PG", + "gke": "gke-Latn-CM", + "gkn": "gkn-Latn-ZZ", + "gko": "gko-Latn-AU", + "gkp": "gkp-Latn-ZZ", + "gku": "gku-Latn-ZA", + "gl": "gl-Latn-ES", + "glb": "glb-Latn-NG", + "glc": "glc-Latn-TD", + "gld": "gld-Cyrl-RU", + "glh": "glh-Arab-AF", + "glj": "glj-Latn-TD", + "glk": "glk-Arab-IR", + "gll": "gll-Latn-AU", + "glo": "glo-Latn-NG", + "glr": "glr-Latn-LR", + "glu": "glu-Latn-TD", + "glw": "glw-Latn-NG", + "gma": "gma-Latn-AU", + "gmb": "gmb-Latn-SB", + "gmd": "gmd-Latn-NG", + "gmg": "gmg-Latn-PG", + "gmh": "gmh-Latn-DE", + "gmm": "gmm-Latn-ZZ", + "gmn": "gmn-Latn-CM", + "gmr": "gmr-Latn-AU", + "gmu": "gmu-Latn-PG", + "gmv": "gmv-Ethi-ZZ", + "gmx": "gmx-Latn-TZ", + "gmy": "gmy-Linb-GR", + "gmz": "gmz-Latn-NG", + "gn": "gn-Latn-PY", + "gna": "gna-Latn-BF", + "gnb": "gnb-Latn-IN", + "gnc": "gnc-Latn-ES", + "gnd": "gnd-Latn-ZZ", + "gne": "gne-Latn-NG", + "gng": "gng-Latn-ZZ", + "gnh": "gnh-Latn-NG", + "gni": "gni-Latn-AU", + "gnj": "gnj-Latn-CI", + "gnk": "gnk-Latn-BW", + "gnl": "gnl-Latn-AU", + "gnm": "gnm-Latn-PG", + "gnn": "gnn-Latn-AU", + "gnq": "gnq-Latn-MY", + "gnr": "gnr-Latn-AU", + "gnt": "gnt-Latn-PG", + "gnu": "gnu-Latn-PG", + "gnw": "gnw-Latn-BO", + "gnz": "gnz-Latn-CF", + "goa": "goa-Latn-CI", + "gob": "gob-Latn-CO", + "goc": "goc-Latn-PG", + "god": "god-Latn-ZZ", + "goe": "goe-Tibt-BT", + "gof": "gof-Ethi-ZZ", + "gog": "gog-Latn-TZ", + "goh": "goh-Latn-DE", + "goi": "goi-Latn-ZZ", + "gok": "gok-Deva-IN", + "gol": "gol-Latn-LR", + "gom": "gom-Deva-IN", + "gon": "gon-Telu-IN", + "goo": "goo-Latn-FJ", + "gop": "gop-Latn-ID", + "goq": "goq-Latn-ID", + "gor": "gor-Latn-ID", + "gos": "gos-Latn-NL", + "got": "got-Goth-UA", + "gou": "gou-Latn-CM", + "gov": "gov-Latn-CI", + "gow": "gow-Latn-TZ", + "gox": "gox-Latn-CD", + "goy": "goy-Latn-TD", + "gpa": "gpa-Latn-NG", + "gpe": "gpe-Latn-GH", + "gpn": "gpn-Latn-PG", + "gqa": "gqa-Latn-NG", + "gqn": "gqn-Latn-BR", + "gqr": "gqr-Latn-TD", + "gra": "gra-Deva-IN", + "gra-Gujr": "gra-Gujr-IN", + "grb": "grb-Latn-ZZ", + "grc": "grc-Cprt-CY", + "grc-Linb": "grc-Linb-GR", + "grd": "grd-Latn-NG", + "grg": "grg-Latn-PG", + "grh": "grh-Latn-NG", + "gri": "gri-Latn-SB", + "grj": "grj-Latn-LR", + "grm": "grm-Latn-MY", + "grq": "grq-Latn-PG", + "grs": "grs-Latn-ID", + "grt": "grt-Beng-IN", + "gru": "gru-Ethi-ET", + "gru-Latn": "gru-Latn-ET", + "grv": "grv-Latn-LR", + "grw": "grw-Latn-ZZ", + "grx": "grx-Latn-PG", + "gry": "gry-Latn-LR", + "grz": "grz-Latn-PG", + "gsl": "gsl-Latn-SN", + "gsn": "gsn-Latn-PG", + "gso": "gso-Latn-CF", + "gsp": "gsp-Latn-PG", + "gsw": "gsw-Latn-CH", + "gta": "gta-Latn-BR", + "gtu": "gtu-Latn-AU", + "gu": "gu-Gujr-IN", + "gua": "gua-Latn-NG", + "gub": "gub-Latn-BR", + "guc": "guc-Latn-CO", + "gud": "gud-Latn-ZZ", + "gue": "gue-Latn-AU", + "guf": "guf-Latn-AU", + "guh": "guh-Latn-CO", + "gui": "gui-Latn-BO", + "guk": "guk-Latn-ET", + "guk-Ethi": "guk-Ethi-ET", + "gul": "gul-Latn-US", + "gum": "gum-Latn-CO", + "gun": "gun-Latn-BR", + "guo": "guo-Latn-CO", + "gup": "gup-Latn-AU", + "guq": "guq-Latn-PY", + "gur": "gur-Latn-GH", + "gut": "gut-Latn-CR", + "guu": "guu-Latn-VE", + "guw": "guw-Latn-ZZ", + "gux": "gux-Latn-ZZ", + "guz": "guz-Latn-KE", + "gv": "gv-Latn-IM", + "gva": "gva-Latn-PY", + "gvc": "gvc-Latn-BR", + "gve": "gve-Latn-PG", + "gvf": "gvf-Latn-ZZ", + "gvj": "gvj-Latn-BR", + "gvl": "gvl-Latn-TD", + "gvm": "gvm-Latn-NG", + "gvn": "gvn-Latn-AU", + "gvo": "gvo-Latn-BR", + "gvp": "gvp-Latn-BR", + "gvr": "gvr-Deva-NP", + "gvs": "gvs-Latn-ZZ", + "gvy": "gvy-Latn-AU", + "gwa": "gwa-Latn-CI", + "gwb": "gwb-Latn-NG", + "gwc": "gwc-Arab-ZZ", + "gwd": "gwd-Latn-ET", + "gwe": "gwe-Latn-TZ", + "gwf": "gwf-Arab-PK", + "gwg": "gwg-Latn-NG", + "gwi": "gwi-Latn-CA", + "gwj": "gwj-Latn-BW", + "gwm": "gwm-Latn-AU", + "gwn": "gwn-Latn-NG", + "gwr": "gwr-Latn-UG", + "gwt": "gwt-Arab-ZZ", + "gwu": "gwu-Latn-AU", + "gww": "gww-Latn-AU", + "gwx": "gwx-Latn-GH", + "gxx": "gxx-Latn-CI", + "gyb": "gyb-Latn-PG", + "gyd": "gyd-Latn-AU", + "gye": "gye-Latn-NG", + "gyf": "gyf-Latn-AU", + "gyg": "gyg-Latn-CF", + "gyi": "gyi-Latn-ZZ", + "gyl": "gyl-Latn-ET", + "gyl-Ethi": "gyl-Ethi-ET", + "gym": "gym-Latn-PA", + "gyn": "gyn-Latn-GY", + "gyo": "gyo-Deva-NP", + "gyr": "gyr-Latn-BO", + "gyy": "gyy-Latn-AU", + "gyz": "gyz-Latn-NG", + "gza": "gza-Latn-SD", + "gzi": "gzi-Arab-IR", + "gzn": "gzn-Latn-ID", + "ha": "ha-Latn-NG", + "ha-CM": "ha-Arab-CM", + "ha-SD": "ha-Arab-SD", + "haa": "haa-Latn-US", + "hac": "hac-Arab-IR", + "had": "had-Latn-ID", + "hae": "hae-Latn-ET", + "hag": "hag-Latn-ZZ", + "hah": "hah-Latn-PG", + "hai": "hai-Latn-CA", + "haj": "haj-Latn-IN", + "haj-Beng": "haj-Beng-IN", + "hak": "hak-Hans-CN", + "hal": "hal-Latn-VN", + "ham": "ham-Latn-ZZ", + "han": "han-Latn-TZ", + "hao": "hao-Latn-PG", + "hap": "hap-Latn-ID", + "haq": "haq-Latn-TZ", + "har": "har-Ethi-ET", + "har-Arab": "har-Arab-ET", + "har-Latn": "har-Latn-ET", + "has": "has-Latn-CA", + "hav": "hav-Latn-CD", + "haw": "haw-Latn-US", + "hax": "hax-Latn-CA", + "hay": "hay-Latn-TZ", + "haz": "haz-Arab-AF", + "hba": "hba-Latn-CD", + "hbb": "hbb-Latn-ZZ", + "hbn": "hbn-Latn-SD", + "hbo": "hbo-Hebr-IL", + "hbu": "hbu-Latn-TL", + "hch": "hch-Latn-MX", + "hdy": "hdy-Ethi-ZZ", + "he": "he-Hebr-IL", + "hed": "hed-Latn-TD", + "heg": "heg-Latn-ID", + "heh": "heh-Latn-TZ", + "hei": "hei-Latn-CA", + "hem": "hem-Latn-CD", + "hgm": "hgm-Latn-NA", + "hgw": "hgw-Latn-PG", + "hhi": "hhi-Latn-PG", + "hhr": "hhr-Latn-SN", + "hhy": "hhy-Latn-ZZ", + "hi": "hi-Deva-IN", + "hi-Latn": "hi-Latn-IN", + "hia": "hia-Latn-ZZ", + "hib": "hib-Latn-PE", + "hid": "hid-Latn-US", + "hif": "hif-Latn-FJ", + "hig": "hig-Latn-ZZ", + "hih": "hih-Latn-ZZ", + "hii": "hii-Takr-IN", + "hii-Deva": "hii-Deva-IN", + "hij": "hij-Latn-CM", + "hik": "hik-Latn-ID", + "hil": "hil-Latn-PH", + "hio": "hio-Latn-BW", + "hir": "hir-Latn-BR", + "hit": "hit-Xsux-TR", + "hiw": "hiw-Latn-VU", + "hix": "hix-Latn-BR", + "hji": "hji-Latn-ID", + "hka": "hka-Latn-TZ", + "hke": "hke-Latn-CD", + "hkh": "hkh-Arab-IN", + "hkh-Deva": "hkh-Deva-IN", + "hkh-Latn": "hkh-Latn-IN", + "hkk": "hkk-Latn-PG", + "hla": "hla-Latn-ZZ", + "hlb": "hlb-Deva-IN", + "hld": "hld-Latn-VN", + "hlt": "hlt-Latn-MM", + "hlu": "hlu-Hluw-TR", + "hma": "hma-Latn-CN", + "hmb": "hmb-Latn-ML", + "hmd": "hmd-Plrd-CN", + "hmf": "hmf-Latn-VN", + "hmj": "hmj-Bopo-CN", + "hmm": "hmm-Latn-CN", + "hmn": "hmn-Latn-CN", + "hmn-Bopo": "hmn-Bopo-CN", + "hmn-Hmng": "hmn-Hmng-CN", + "hmp": "hmp-Latn-CN", + "hmq": "hmq-Bopo-CN", + "hmr": "hmr-Latn-IN", + "hms": "hms-Latn-CN", + "hmt": "hmt-Latn-ZZ", + "hmu": "hmu-Latn-ID", + "hmv": "hmv-Latn-VN", + "hmw": "hmw-Latn-CN", + "hmy": "hmy-Latn-CN", + "hmz": "hmz-Latn-CN", + "hmz-Plrd": "hmz-Plrd-CN", + "hna": "hna-Latn-CM", + "hnd": "hnd-Arab-PK", + "hne": "hne-Deva-IN", + "hng": "hng-Latn-AO", + "hnh": "hnh-Latn-BW", + "hni": "hni-Latn-CN", + "hnj": "hnj-Hmnp-US", + "hnj-AU": "hnj-Laoo-AU", + "hnj-CN": "hnj-Laoo-CN", + "hnj-FR": "hnj-Laoo-FR", + "hnj-GF": "hnj-Laoo-GF", + "hnj-LA": "hnj-Laoo-LA", + "hnj-Laoo": "hnj-Laoo-LA", + "hnj-MM": "hnj-Laoo-MM", + "hnj-SR": "hnj-Laoo-SR", + "hnj-TH": "hnj-Laoo-TH", + "hnj-US": "hnj-Hmnp-US", + "hnj-VN": "hnj-Laoo-VN", + "hnn": "hnn-Latn-PH", + "hno": "hno-Arab-PK", + "hns": "hns-Latn-SR", + "ho": "ho-Latn-PG", + "hoa": "hoa-Latn-SB", + "hob": "hob-Latn-PG", + "hoc": "hoc-Deva-IN", + "hod": "hod-Latn-NG", + "hoe": "hoe-Latn-NG", + "hoh": "hoh-Arab-OM", + "hoi": "hoi-Latn-US", + "hoj": "hoj-Deva-IN", + "hol": "hol-Latn-AO", + "hom": "hom-Latn-SS", + "hoo": "hoo-Latn-CD", + "hop": "hop-Latn-US", + "hor": "hor-Latn-TD", + "hot": "hot-Latn-ZZ", + "hov": "hov-Latn-ID", + "how": "how-Hani-CN", + "hoy": "hoy-Deva-IN", + "hpo": "hpo-Mymr-MM", + "hr": "hr-Latn-HR", + "hra": "hra-Latn-IN", + "hrc": "hrc-Latn-PG", + "hre": "hre-Latn-VN", + "hrk": "hrk-Latn-ID", + "hrm": "hrm-Latn-CN", + "hrm-Hmng": "hrm-Hmng-CN", + "hro": "hro-Latn-VN", + "hrp": "hrp-Latn-AU", + "hrt": "hrt-Syrc-TR", + "hru": "hru-Latn-IN", + "hrw": "hrw-Latn-PG", + "hrx": "hrx-Latn-BR", + "hrz": "hrz-Arab-IR", + "hsb": "hsb-Latn-DE", + "hsn": "hsn-Hans-CN", + "hss": "hss-Arab-OM", + "ht": "ht-Latn-HT", + "hti": "hti-Latn-ID", + "hto": "hto-Latn-CO", + "hts": "hts-Latn-TZ", + "htu": "htu-Latn-ID", + "htx": "htx-Xsux-TR", + "hu": "hu-Latn-HU", + "hub": "hub-Latn-PE", + "huc": "huc-Latn-BW", + "hud": "hud-Latn-ID", + "hue": "hue-Latn-MX", + "huf": "huf-Latn-PG", + "hug": "hug-Latn-PE", + "huh": "huh-Latn-CL", + "hui": "hui-Latn-ZZ", + "huk": "huk-Latn-ID", + "hul": "hul-Latn-PG", + "hum": "hum-Latn-CD", + "hup": "hup-Latn-US", + "hur": "hur-Latn-CA", + "hus": "hus-Latn-MX", + "hut": "hut-Deva-NP", + "hut-Tibt": "hut-Tibt-NP", + "huu": "huu-Latn-PE", + "huv": "huv-Latn-MX", + "huw": "huw-Latn-ID", + "hux": "hux-Latn-PE", + "huy": "huy-Hebr-IL", + "huz": "huz-Cyrl-RU", + "hvc": "hvc-Latn-HT", + "hve": "hve-Latn-MX", + "hvk": "hvk-Latn-NC", + "hvn": "hvn-Latn-ID", + "hvv": "hvv-Latn-MX", + "hwa": "hwa-Latn-CI", + "hwc": "hwc-Latn-US", + "hwo": "hwo-Latn-NG", + "hy": "hy-Armn-AM", + "hya": "hya-Latn-CM", + "hyw": "hyw-Armn-AM", + "hz": "hz-Latn-NA", + "ia": "ia-Latn-001", + "iai": "iai-Latn-NC", + "ian": "ian-Latn-ZZ", + "iar": "iar-Latn-ZZ", + "iba": "iba-Latn-MY", + "ibb": "ibb-Latn-NG", + "ibd": "ibd-Latn-AU", + "ibe": "ibe-Latn-NG", + "ibg": "ibg-Latn-PH", + "ibh": "ibh-Latn-VN", + "ibl": "ibl-Latn-PH", + "ibm": "ibm-Latn-NG", + "ibn": "ibn-Latn-NG", + "ibr": "ibr-Latn-NG", + "ibu": "ibu-Latn-ID", + "iby": "iby-Latn-ZZ", + "ica": "ica-Latn-ZZ", + "ich": "ich-Latn-ZZ", + "icr": "icr-Latn-CO", + "id": "id-Latn-ID", + "ida": "ida-Latn-KE", + "idb": "idb-Latn-IN", + "idc": "idc-Latn-NG", + "idd": "idd-Latn-ZZ", + "ide": "ide-Latn-NG", + "idi": "idi-Latn-ZZ", + "idr": "idr-Latn-SS", + "ids": "ids-Latn-NG", + "idt": "idt-Latn-TL", + "idu": "idu-Latn-ZZ", + "ie": "ie-Latn-001", + "ifa": "ifa-Latn-PH", + "ifb": "ifb-Latn-PH", + "ife": "ife-Latn-TG", + "iff": "iff-Latn-VU", + "ifk": "ifk-Latn-PH", + "ifm": "ifm-Latn-CG", + "ifu": "ifu-Latn-PH", + "ify": "ify-Latn-PH", + "ig": "ig-Latn-NG", + "igb": "igb-Latn-ZZ", + "ige": "ige-Latn-ZZ", + "igg": "igg-Latn-PG", + "igl": "igl-Latn-NG", + "igm": "igm-Latn-PG", + "ign": "ign-Latn-BO", + "igo": "igo-Latn-PG", + "igs": "igs-Latn-001", + "igs-Grek": "igs-Grek-001", + "igw": "igw-Latn-NG", + "ihb": "ihb-Latn-ID", + "ihi": "ihi-Latn-NG", + "ihp": "ihp-Latn-ID", + "ihw": "ihw-Latn-AU", + "ii": "ii-Yiii-CN", + "iin": "iin-Latn-AU", + "ijc": "ijc-Latn-NG", + "ije": "ije-Latn-NG", + "ijj": "ijj-Latn-ZZ", + "ijn": "ijn-Latn-NG", + "ijs": "ijs-Latn-NG", + "ik": "ik-Latn-US", + "iki": "iki-Latn-NG", + "ikk": "ikk-Latn-ZZ", + "ikl": "ikl-Latn-NG", + "iko": "iko-Latn-NG", + "ikp": "ikp-Latn-NG", + "ikr": "ikr-Latn-AU", + "ikt": "ikt-Latn-CA", + "ikt-Cans": "ikt-Cans-CA", + "ikv": "ikv-Latn-NG", + "ikw": "ikw-Latn-ZZ", + "ikx": "ikx-Latn-ZZ", + "ikz": "ikz-Latn-TZ", + "ila": "ila-Latn-ID", + "ilb": "ilb-Latn-ZM", + "ilg": "ilg-Latn-AU", + "ili": "ili-Latn-CN", + "ili-Arab": "ili-Arab-CN", + "ili-Cyrl": "ili-Cyrl-KZ", + "ilk": "ilk-Latn-PH", + "ilm": "ilm-Latn-MY", + "ilo": "ilo-Latn-PH", + "ilp": "ilp-Latn-PH", + "ilu": "ilu-Latn-ID", + "ilv": "ilv-Latn-NG", + "imi": "imi-Latn-PG", + "iml": "iml-Latn-US", + "imn": "imn-Latn-PG", + "imo": "imo-Latn-ZZ", + "imr": "imr-Latn-ID", + "ims": "ims-Latn-IT", + "imt": "imt-Latn-SS", + "imy": "imy-Lyci-TR", + "in": "id-Latn-ID", + "inb": "inb-Latn-CO", + "ing": "ing-Latn-US", + "inh": "inh-Cyrl-RU", + "inj": "inj-Latn-CO", + "inn": "inn-Latn-PH", + "ino": "ino-Latn-PG", + "inp": "inp-Latn-PE", + "int": "int-Mymr-MM", + "io": "io-Latn-001", + "ior": "ior-Ethi-ET", + "iou": "iou-Latn-ZZ", + "iow": "iow-Latn-US", + "ipi": "ipi-Latn-PG", + "ipo": "ipo-Latn-PG", + "iqu": "iqu-Latn-PE", + "iqw": "iqw-Latn-NG", + "ire": "ire-Latn-ID", + "irh": "irh-Latn-ID", + "iri": "iri-Latn-ZZ", + "irk": "irk-Latn-TZ", + "irn": "irn-Latn-BR", + "iru": "iru-Taml-IN", + "iru-Mlym": "iru-Mlym-IN", + "irx": "irx-Latn-ID", + "iry": "iry-Latn-PH", + "is": "is-Latn-IS", + "isa": "isa-Latn-PG", + "isc": "isc-Latn-PE", + "isd": "isd-Latn-PH", + "ish": "ish-Latn-NG", + "isi": "isi-Latn-NG", + "isk": "isk-Arab-AF", + "isk-Cyrl": "isk-Cyrl-TJ", + "ism": "ism-Latn-ID", + "isn": "isn-Latn-TZ", + "iso": "iso-Latn-NG", + "ist": "ist-Latn-HR", + "isu": "isu-Latn-CM", + "it": "it-Latn-IT", + "itb": "itb-Latn-PH", + "itd": "itd-Latn-ID", + "ite": "ite-Latn-BO", + "iti": "iti-Latn-PH", + "itk": "itk-Hebr-IT", + "itl": "itl-Cyrl-RU", + "itm": "itm-Latn-NG", + "ito": "ito-Latn-BO", + "itr": "itr-Latn-PG", + "its": "its-Latn-NG", + "itt": "itt-Latn-PH", + "itv": "itv-Latn-PH", + "itw": "itw-Latn-NG", + "itx": "itx-Latn-ID", + "ity": "ity-Latn-PH", + "itz": "itz-Latn-GT", + "iu": "iu-Cans-CA", + "ium": "ium-Latn-CN", + "ium-Hani": "ium-Hani-CN", + "ium-Laoo": "ium-Laoo-LA", + "ium-Thai": "ium-Thai-TH", + "ivb": "ivb-Latn-PH", + "ivv": "ivv-Latn-PH", + "iw": "he-Hebr-IL", + "iwk": "iwk-Latn-PH", + "iwm": "iwm-Latn-ZZ", + "iwo": "iwo-Latn-ID", + "iws": "iws-Latn-ZZ", + "ixc": "ixc-Latn-MX", + "ixl": "ixl-Latn-GT", + "iya": "iya-Latn-NG", + "iyo": "iyo-Latn-CM", + "iyx": "iyx-Latn-CG", + "izh": "izh-Latn-RU", + "izi": "eza-Latn-ZZ", + "izr": "izr-Latn-NG", + "izz": "izz-Latn-NG", + "ja": "ja-Jpan-JP", + "jaa": "jaa-Latn-BR", + "jab": "jab-Latn-ZZ", + "jac": "jac-Latn-GT", + "jad": "jad-Arab-GN", + "jae": "jae-Latn-PG", + "jaf": "jaf-Latn-NG", + "jah": "jah-Latn-MY", + "jaj": "jaj-Latn-SB", + "jak": "jak-Latn-MY", + "jal": "jal-Latn-ID", + "jam": "jam-Latn-JM", + "jan": "jan-Latn-AU", + "jao": "jao-Latn-AU", + "jaq": "jaq-Latn-ID", + "jar": "jgk-Latn-ZZ", + "jas": "jas-Latn-NC", + "jat": "jat-Arab-AF", + "jau": "jau-Latn-ID", + "jax": "jax-Latn-ID", + "jay": "jay-Latn-AU", + "jaz": "jaz-Latn-NC", + "jbe": "jbe-Hebr-IL", + "jbi": "jbi-Latn-AU", + "jbj": "jbj-Latn-ID", + "jbk": "jbk-Latn-PG", + "jbm": "jbm-Latn-NG", + "jbn": "jbn-Arab-LY", + "jbo": "jbo-Latn-001", + "jbr": "jbr-Latn-ID", + "jbt": "jbt-Latn-BR", + "jbu": "jbu-Latn-ZZ", + "jbw": "jbw-Latn-AU", + "jct": "jct-Cyrl-UA", + "jct-Latn": "jct-Latn-UA", + "jda": "jda-Tibt-IN", + "jdg": "jdg-Arab-PK", + "jdt": "jdt-Cyrl-RU", + "jdt-Hebr": "jdt-Hebr-RU", + "jdt-Latn": "jdt-Latn-AZ", + "jeb": "jeb-Latn-PE", + "jee": "jee-Deva-NP", + "jeh": "jeh-Latn-VN", + "jeh-Laoo": "jeh-Laoo-LA", + "jei": "jei-Latn-ID", + "jek": "jek-Latn-CI", + "jel": "jel-Latn-ID", + "jen": "jen-Latn-ZZ", + "jer": "jer-Latn-NG", + "jet": "jet-Latn-PG", + "jeu": "jeu-Latn-TD", + "jgb": "jgb-Latn-CD", + "jge": "jge-Geor-GE", + "jge-Hebr": "jge-Hebr-IL", + "jgk": "jgk-Latn-ZZ", + "jgo": "jgo-Latn-CM", + "jhi": "jhi-Latn-MY", + "ji": "yi-Hebr-001", + "jia": "jia-Latn-CM", + "jib": "jib-Latn-ZZ", + "jic": "jic-Latn-HN", + "jid": "jid-Latn-NG", + "jie": "jie-Latn-NG", + "jig": "jig-Latn-AU", + "jil": "jil-Latn-PG", + "jim": "jim-Latn-CM", + "jit": "jit-Latn-TZ", + "jiu": "jiu-Latn-CN", + "jiv": "jiv-Latn-EC", + "jiy": "jiy-Latn-CN", + "jje": "jje-Hang-KR", + "jjr": "jjr-Latn-NG", + "jka": "jka-Latn-ID", + "jkm": "jkm-Mymr-MM", + "jkm-Brai": "jkm-Brai-MM", + "jkm-Latn": "jkm-Latn-MM", + "jko": "jko-Latn-PG", + "jku": "jku-Latn-NG", + "jle": "jle-Latn-SD", + "jma": "jma-Latn-PG", + "jmb": "jmb-Latn-NG", + "jmc": "jmc-Latn-TZ", + "jmd": "jmd-Latn-ID", + "jmi": "jmi-Latn-NG", + "jml": "jml-Deva-NP", + "jmn": "jmn-Latn-MM", + "jmr": "jmr-Latn-GH", + "jms": "jms-Latn-NG", + "jmw": "jmw-Latn-PG", + "jmx": "jmx-Latn-MX", + "jna": "jna-Takr-IN", + "jnd": "jnd-Arab-PK", + "jng": "jng-Latn-AU", + "jni": "jni-Latn-NG", + "jnj": "jnj-Latn-ET", + "jnj-Ethi": "jnj-Ethi-ET", + "jnl": "jnl-Deva-IN", + "jns": "jns-Deva-IN", + "jns-Latn": "jns-Latn-IN", + "jns-Takr": "jns-Takr-IN", + "job": "job-Latn-CD", + "jod": "jod-Latn-CI", + "jog": "jog-Arab-PK", + "jor": "jor-Latn-BO", + "jow": "jow-Latn-ML", + "jpa": "jpa-Hebr-PS", + "jpr": "jpr-Hebr-IL", + "jqr": "jqr-Latn-PE", + "jra": "jra-Latn-ZZ", + "jrr": "jrr-Latn-NG", + "jrt": "jrt-Latn-NG", + "jru": "jru-Latn-VE", + "jua": "jua-Latn-BR", + "jub": "jub-Latn-NG", + "jud": "jud-Latn-CI", + "juh": "juh-Latn-NG", + "jui": "jui-Latn-AU", + "juk": "juk-Latn-NG", + "jul": "jul-Deva-NP", + "jum": "jum-Latn-SD", + "jun": "jun-Orya-IN", + "juo": "juo-Latn-NG", + "jup": "jup-Latn-BR", + "jur": "jur-Latn-BR", + "jut": "jut-Latn-DK", + "juu": "juu-Latn-NG", + "juw": "juw-Latn-NG", + "juy": "juy-Orya-IN", + "jv": "jv-Latn-ID", + "jvd": "jvd-Latn-ID", + "jvn": "jvn-Latn-SR", + "jw": "jv-Latn-ID", + "jwi": "jwi-Latn-GH", + "jya": "jya-Tibt-CN", + "jye": "jye-Hebr-IL", + "jyy": "jyy-Latn-TD", + "ka": "ka-Geor-GE", + "kaa": "kaa-Cyrl-UZ", + "kab": "kab-Latn-DZ", + "kac": "kac-Latn-MM", + "kad": "kad-Latn-ZZ", + "kag": "kag-Latn-MY", + "kah": "kah-Latn-CF", + "kai": "kai-Latn-ZZ", + "kaj": "kaj-Latn-NG", + "kak": "kak-Latn-PH", + "kam": "kam-Latn-KE", + "kao": "kao-Latn-ML", + "kap": "kap-Cyrl-RU", + "kaq": "kaq-Latn-PE", + "kav": "kav-Latn-BR", + "kaw": "kaw-Kawi-ID", + "kax": "kax-Latn-ID", + "kay": "kay-Latn-BR", + "kba": "kba-Latn-AU", + "kbb": "kbb-Latn-BR", + "kbc": "kbc-Latn-BR", + "kbd": "kbd-Cyrl-RU", + "kbe": "kbe-Latn-AU", + "kbh": "kbh-Latn-CO", + "kbi": "kbi-Latn-ID", + "kbj": "kbj-Latn-CD", + "kbk": "kbk-Latn-PG", + "kbl": "kbl-Latn-TD", + "kbm": "kbm-Latn-ZZ", + "kbn": "kbn-Latn-CF", + "kbo": "kbo-Latn-SS", + "kbp": "kbp-Latn-ZZ", + "kbq": "kbq-Latn-ZZ", + "kbr": "kbr-Latn-ET", + "kbr-Ethi": "kbr-Ethi-ET", + "kbs": "kbs-Latn-GA", + "kbt": "kbt-Latn-PG", + "kbu": "kbu-Arab-PK", + "kbv": "kbv-Latn-ID", + "kbw": "kbw-Latn-PG", + "kbx": "kbx-Latn-ZZ", + "kby": "kby-Arab-NE", + "kbz": "kbz-Latn-NG", + "kca": "kca-Cyrl-RU", + "kcb": "kcb-Latn-PG", + "kcc": "kcc-Latn-NG", + "kcd": "kcd-Latn-ID", + "kce": "kce-Latn-NG", + "kcf": "kcf-Latn-NG", + "kcg": "kcg-Latn-NG", + "kch": "kch-Latn-NG", + "kci": "kci-Latn-NG", + "kcj": "kcj-Latn-GW", + "kck": "kck-Latn-ZW", + "kcl": "kcl-Latn-ZZ", + "kcm": "kcm-Latn-CF", + "kcn": "kcn-Latn-UG", + "kco": "kco-Latn-PG", + "kcp": "kcp-Latn-SD", + "kcq": "kcq-Latn-NG", + "kcs": "kcs-Latn-NG", + "kct": "kct-Latn-ZZ", + "kcu": "kcu-Latn-TZ", + "kcv": "kcv-Latn-CD", + "kcw": "kcw-Latn-CD", + "kcz": "kcz-Latn-TZ", + "kda": "kda-Latn-AU", + "kdc": "kdc-Latn-TZ", + "kdd": "kdd-Latn-AU", + "kde": "kde-Latn-TZ", + "kdf": "kdf-Latn-PG", + "kdg": "kdg-Latn-CD", + "kdh": "kdh-Latn-TG", + "kdi": "kdi-Latn-UG", + "kdj": "kdj-Latn-UG", + "kdk": "kdk-Latn-NC", + "kdl": "kdl-Latn-ZZ", + "kdm": "kdm-Latn-NG", + "kdn": "kdn-Latn-ZW", + "kdp": "kdp-Latn-NG", + "kdq": "kdq-Beng-IN", + "kdr": "kdr-Latn-LT", + "kdr-Cyrl": "kdr-Cyrl-UA", + "kdt": "kdt-Thai-TH", + "kdw": "kdw-Latn-ID", + "kdx": "kdx-Latn-NG", + "kdy": "kdy-Latn-ID", + "kdz": "kdz-Latn-CM", + "kea": "kea-Latn-CV", + "keb": "keb-Latn-GA", + "kec": "kec-Latn-SD", + "ked": "ked-Latn-TZ", + "kee": "kee-Latn-US", + "kef": "kef-Latn-TG", + "keg": "keg-Latn-SD", + "keh": "keh-Latn-PG", + "kei": "kei-Latn-ID", + "kek": "kek-Latn-GT", + "kel": "kel-Latn-CD", + "kem": "kem-Latn-TL", + "ken": "ken-Latn-CM", + "keo": "keo-Latn-UG", + "ker": "ker-Latn-TD", + "kes": "kes-Latn-NG", + "ket": "ket-Cyrl-RU", + "keu": "keu-Latn-TG", + "kew": "kew-Latn-PG", + "kex": "kex-Deva-IN", + "kex-Gujr": "kex-Gujr-IN", + "key": "key-Telu-IN", + "kez": "kez-Latn-ZZ", + "kfa": "kfa-Knda-IN", + "kfb": "kfb-Deva-IN", + "kfc": "kfc-Telu-IN", + "kfd": "kfd-Knda-IN", + "kfe": "kfe-Taml-IN", + "kff": "kff-Latn-IN", + "kff-Deva": "kff-Deva-IN", + "kff-Orya": "kff-Orya-IN", + "kff-Telu": "kff-Telu-IN", + "kfh": "kfh-Mlym-IN", + "kfi": "kfi-Taml-IN", + "kfi-Knda": "kfi-Knda-IN", + "kfk": "kfk-Deva-IN", + "kfk-Takr": "kfk-Takr-IN", + "kfl": "kfl-Latn-CM", + "kfm": "kfm-Arab-IR", + "kfn": "kfn-Latn-CM", + "kfo": "kfo-Latn-CI", + "kfp": "kfp-Deva-IN", + "kfq": "kfq-Deva-IN", + "kfr": "kfr-Deva-IN", + "kfs": "kfs-Deva-IN", + "kfv": "kfv-Latn-IN", + "kfw": "kfw-Latn-IN", + "kfx": "kfx-Deva-IN", + "kfx-Takr": "kfx-Takr-IN", + "kfy": "kfy-Deva-IN", + "kfz": "kfz-Latn-BF", + "kg": "kg-Latn-CD", + "kga": "kga-Latn-CI", + "kgb": "kgb-Latn-ID", + "kge": "kge-Latn-ID", + "kgf": "kgf-Latn-ZZ", + "kgj": "kgj-Deva-NP", + "kgk": "kgk-Latn-BR", + "kgl": "kgl-Latn-AU", + "kgm": "kgm-Latn-BR", + "kgo": "kgo-Latn-SD", + "kgp": "kgp-Latn-BR", + "kgq": "kgq-Latn-ID", + "kgr": "kgr-Latn-ID", + "kgs": "kgs-Latn-AU", + "kgt": "kgt-Latn-NG", + "kgu": "kgu-Latn-PG", + "kgv": "kgv-Latn-ID", + "kgw": "kgw-Latn-ID", + "kgx": "kgx-Latn-ID", + "kgy": "kgy-Deva-NP", + "kha": "kha-Latn-IN", + "khb": "khb-Talu-CN", + "khc": "khc-Latn-ID", + "khd": "khd-Latn-ID", + "khe": "khe-Latn-ID", + "khf": "khf-Thai-LA", + "khg": "khg-Tibt-CN", + "khh": "khh-Latn-ID", + "khj": "khj-Latn-NG", + "khl": "khl-Latn-PG", + "khn": "khn-Deva-IN", + "khp": "khp-Latn-ID", + "khq": "khq-Latn-ML", + "khr": "khr-Latn-IN", + "khr-Deva": "khr-Deva-IN", + "khs": "khs-Latn-ZZ", + "kht": "kht-Mymr-IN", + "khu": "khu-Latn-AO", + "khv": "khv-Cyrl-RU", + "khw": "khw-Arab-PK", + "khx": "khx-Latn-CD", + "khy": "khy-Latn-CD", + "khz": "khz-Latn-ZZ", + "ki": "ki-Latn-KE", + "kia": "kia-Latn-TD", + "kib": "kib-Latn-SD", + "kic": "kic-Latn-US", + "kid": "kid-Latn-CM", + "kie": "kie-Latn-TD", + "kif": "kif-Deva-NP", + "kig": "kig-Latn-ID", + "kih": "kih-Latn-PG", + "kij": "kij-Latn-ZZ", + "kil": "kil-Latn-NG", + "kim": "kim-Cyrl-RU", + "kio": "kio-Latn-US", + "kip": "kip-Deva-NP", + "kiq": "kiq-Latn-ID", + "kis": "kis-Latn-PG", + "kit": "kit-Latn-PG", + "kiu": "kiu-Latn-TR", + "kiv": "kiv-Latn-TZ", + "kiw": "kiw-Latn-ZZ", + "kix": "kix-Latn-IN", + "kiy": "kiy-Latn-ID", + "kiz": "kiz-Latn-TZ", + "kj": "kj-Latn-NA", + "kja": "kja-Latn-ID", + "kjb": "kjb-Latn-GT", + "kjc": "kjc-Latn-ID", + "kjd": "kjd-Latn-ZZ", + "kje": "kje-Latn-ID", + "kjg": "kjg-Laoo-LA", + "kjh": "kjh-Cyrl-RU", + "kji": "kji-Latn-SB", + "kjj": "kjj-Latn-AZ", + "kjk": "kjk-Latn-ID", + "kjl": "kjl-Deva-NP", + "kjm": "kjm-Latn-VN", + "kjn": "kjn-Latn-AU", + "kjo": "kjo-Deva-IN", + "kjp": "kjp-Mymr-MM", + "kjp-Thai": "kjp-Thai-TH", + "kjq": "kjq-Latn-US", + "kjr": "kjr-Latn-ID", + "kjs": "kjs-Latn-ZZ", + "kjt": "kjt-Thai-TH", + "kju": "kju-Latn-US", + "kjx": "kjx-Latn-PG", + "kjy": "kjy-Latn-ZZ", + "kk": "kk-Cyrl-KZ", + "kk-AF": "kk-Arab-AF", + "kk-Arab": "kk-Arab-CN", + "kk-CN": "kk-Arab-CN", + "kk-IR": "kk-Arab-IR", + "kk-MN": "kk-Arab-MN", + "kka": "kka-Latn-NG", + "kkb": "kkb-Latn-ID", + "kkc": "kkc-Latn-ZZ", + "kkd": "kkd-Latn-NG", + "kke": "kke-Latn-GN", + "kke-Arab": "kke-Arab-GN", + "kkf": "kkf-Tibt-IN", + "kkg": "kkg-Latn-PH", + "kkh": "kkh-Lana-MM", + "kki": "kki-Latn-TZ", + "kkj": "kkj-Latn-CM", + "kkk": "kkk-Latn-SB", + "kkl": "kkl-Latn-ID", + "kkm": "kkm-Latn-NG", + "kko": "kko-Latn-SD", + "kkp": "kkp-Latn-AU", + "kkq": "kkq-Latn-CD", + "kkr": "kkr-Latn-NG", + "kks": "kks-Latn-NG", + "kkt": "kkt-Deva-NP", + "kku": "kku-Latn-NG", + "kkv": "kkv-Latn-ID", + "kkw": "kkw-Latn-CG", + "kkx": "kkx-Latn-ID", + "kky": "kky-Latn-AU", + "kkz": "kkz-Latn-CA", + "kl": "kl-Latn-GL", + "kla": "kla-Latn-US", + "klb": "klb-Latn-MX", + "klc": "klc-Latn-CM", + "kld": "kld-Latn-AU", + "kle": "kle-Deva-NP", + "klf": "klf-Latn-TD", + "klg": "klg-Latn-PH", + "klh": "klh-Latn-PG", + "kli": "kli-Latn-ID", + "klj": "klj-Arab-IR", + "klk": "klk-Latn-NG", + "kll": "kll-Latn-PH", + "klm": "klm-Latn-PG", + "kln": "kln-Latn-KE", + "klo": "klo-Latn-NG", + "klp": "klp-Latn-PG", + "klq": "klq-Latn-ZZ", + "klr": "klr-Deva-NP", + "kls": "kls-Latn-PK", + "kls-Arab": "kls-Arab-PK", + "klt": "klt-Latn-ZZ", + "klu": "klu-Latn-LR", + "klv": "klv-Latn-VU", + "klw": "klw-Latn-ID", + "klx": "klx-Latn-ZZ", + "kly": "kly-Latn-ID", + "klz": "klz-Latn-ID", + "km": "km-Khmr-KH", + "kma": "kma-Latn-GH", + "kmb": "kmb-Latn-AO", + "kmc": "kmc-Latn-CN", + "kmc-Hani": "kmc-Hani-CN", + "kmd": "kmd-Latn-PH", + "kme": "kme-Latn-CM", + "kmf": "kmf-Latn-PG", + "kmg": "kmg-Latn-PG", + "kmh": "kmh-Latn-ZZ", + "kmi": "kmi-Latn-NG", + "kmj": "kmj-Deva-IN", + "kmk": "kmk-Latn-PH", + "kml": "kml-Latn-PH", + "kmm": "kmm-Latn-IN", + "kmn": "kmn-Latn-PG", + "kmo": "kmo-Latn-ZZ", + "kmp": "kmp-Latn-CM", + "kmq": "kmq-Latn-ET", + "kms": "kms-Latn-ZZ", + "kmt": "kmt-Latn-ID", + "kmu": "kmu-Latn-ZZ", + "kmv": "kmv-Latn-BR", + "kmw": "kmw-Latn-ZZ", + "kmx": "kmx-Latn-PG", + "kmy": "kmy-Latn-NG", + "kmz": "kmz-Arab-IR", + "kn": "kn-Knda-IN", + "kna": "kna-Latn-NG", + "knb": "knb-Latn-PH", + "knd": "knd-Latn-ID", + "kne": "kne-Latn-PH", + "knf": "knf-Latn-GW", + "kni": "kni-Latn-NG", + "knj": "knj-Latn-GT", + "knk": "knk-Latn-SL", + "knk-Arab": "knk-Arab-SL", + "knl": "knl-Latn-ID", + "knm": "knm-Latn-BR", + "kno": "kno-Latn-SL", + "knp": "knp-Latn-ZZ", + "knq": "knq-Latn-MY", + "knr": "knr-Latn-PG", + "kns": "kns-Latn-MY", + "kns-Thai": "kns-Thai-TH", + "knt": "knt-Latn-BR", + "knu": "knu-Latn-GN", + "knv": "knv-Latn-PG", + "knw": "knw-Latn-NA", + "knx": "knx-Latn-ID", + "kny": "kny-Latn-CD", + "knz": "knz-Latn-BF", + "ko": "ko-Kore-KR", + "koa": "koa-Latn-PG", + "koc": "koc-Latn-NG", + "kod": "kod-Latn-ID", + "koe": "koe-Latn-SS", + "kof": "kof-Latn-NG", + "kog": "kog-Latn-CO", + "koh": "koh-Latn-CG", + "koi": "koi-Cyrl-RU", + "kok": "kok-Deva-IN", + "kol": "kol-Latn-ZZ", + "koo": "koo-Latn-UG", + "kop": "kop-Latn-PG", + "koq": "koq-Latn-GA", + "kos": "kos-Latn-FM", + "kot": "kot-Latn-CM", + "kou": "kou-Latn-TD", + "kov": "kov-Latn-NG", + "kow": "kow-Latn-NG", + "koy": "koy-Latn-US", + "koz": "koz-Latn-ZZ", + "kpa": "kpa-Latn-NG", + "kpc": "kpc-Latn-CO", + "kpd": "kpd-Latn-ID", + "kpe": "kpe-Latn-LR", + "kpf": "kpf-Latn-ZZ", + "kpg": "kpg-Latn-FM", + "kph": "kph-Latn-GH", + "kpi": "kpi-Latn-ID", + "kpj": "kpj-Latn-BR", + "kpk": "kpk-Latn-NG", + "kpl": "kpl-Latn-CD", + "kpm": "kpm-Latn-VN", + "kpn": "kpn-Latn-BR", + "kpo": "kpo-Latn-ZZ", + "kpq": "kpq-Latn-ID", + "kpr": "kpr-Latn-ZZ", + "kps": "kps-Latn-ID", + "kpt": "kpt-Cyrl-RU", + "kpu": "kpu-Latn-ID", + "kpw": "kpw-Latn-PG", + "kpx": "kpx-Latn-ZZ", + "kpy": "kpy-Cyrl-RU", + "kpz": "kpz-Latn-UG", + "kqa": "kqa-Latn-PG", + "kqb": "kqb-Latn-ZZ", + "kqc": "kqc-Latn-PG", + "kqd": "kqd-Syrc-IQ", + "kqe": "kqe-Latn-PH", + "kqf": "kqf-Latn-ZZ", + "kqg": "kqg-Latn-BF", + "kqh": "kqh-Latn-TZ", + "kqi": "kqi-Latn-PG", + "kqj": "kqj-Latn-PG", + "kqk": "kqk-Latn-BJ", + "kql": "kql-Latn-PG", + "kqm": "kqm-Latn-CI", + "kqn": "kqn-Latn-ZM", + "kqo": "kqo-Latn-LR", + "kqp": "kqp-Latn-TD", + "kqq": "kqq-Latn-BR", + "kqr": "kqr-Latn-MY", + "kqs": "kqs-Latn-ZZ", + "kqt": "kqt-Latn-MY", + "kqu": "kqu-Latn-ZA", + "kqv": "kqv-Latn-ID", + "kqw": "kqw-Latn-PG", + "kqx": "kqx-Latn-CM", + "kqy": "kqy-Ethi-ZZ", + "kqz": "kqz-Latn-ZA", + "kr": "kr-Latn-ZZ", + "kra": "kra-Deva-NP", + "krb": "krb-Latn-US", + "krc": "krc-Cyrl-RU", + "krd": "krd-Latn-TL", + "kre": "kre-Latn-BR", + "krf": "krf-Latn-VU", + "krh": "krh-Latn-NG", + "kri": "kri-Latn-SL", + "krj": "krj-Latn-PH", + "krk": "krk-Cyrl-RU", + "krl": "krl-Latn-RU", + "krn": "krn-Latn-LR", + "krp": "krp-Latn-NG", + "krr": "krr-Khmr-KH", + "krs": "krs-Latn-ZZ", + "krt": "krt-Latn-NE", + "kru": "kru-Deva-IN", + "krv": "krv-Khmr-KH", + "krw": "krw-Latn-LR", + "krx": "krx-Latn-SN", + "kry": "kry-Latn-AZ", + "krz": "krz-Latn-ID", + "ks": "ks-Arab-IN", + "ksa": "ksa-Latn-NG", + "ksb": "ksb-Latn-TZ", + "ksc": "ksc-Latn-PH", + "ksd": "ksd-Latn-ZZ", + "kse": "kse-Latn-PG", + "ksf": "ksf-Latn-CM", + "ksg": "ksg-Latn-SB", + "ksh": "ksh-Latn-DE", + "ksi": "ksi-Latn-PG", + "ksj": "ksj-Latn-ZZ", + "ksk": "ksk-Latn-US", + "ksl": "ksl-Latn-PG", + "ksm": "ksm-Latn-NG", + "ksn": "ksn-Latn-PH", + "kso": "kso-Latn-NG", + "ksp": "ksp-Latn-CF", + "ksq": "ksq-Latn-NG", + "ksr": "ksr-Latn-ZZ", + "kss": "kss-Latn-LR", + "kst": "kst-Latn-BF", + "ksu": "ksu-Mymr-IN", + "ksv": "ksv-Latn-CD", + "ksw": "ksw-Mymr-MM", + "ksw-Latn": "ksw-Latn-MM", + "ksx": "ksx-Latn-ID", + "ksz": "ksz-Deva-IN", + "kta": "kta-Latn-VN", + "ktb": "ktb-Ethi-ZZ", + "ktc": "ktc-Latn-NG", + "ktd": "ktd-Latn-AU", + "ktf": "ktf-Latn-CD", + "ktg": "ktg-Latn-AU", + "kth": "kth-Latn-TD", + "kti": "kti-Latn-ID", + "ktj": "ktj-Latn-CI", + "ktk": "ktk-Latn-PG", + "ktl": "ktl-Arab-IR", + "ktm": "ktm-Latn-ZZ", + "ktn": "ktn-Latn-BR", + "kto": "kto-Latn-ZZ", + "ktp": "ktp-Plrd-CN", + "ktq": "ktq-Latn-PH", + "ktr": "dtp-Latn-MY", + "kts": "kts-Latn-ID", + "ktt": "ktt-Latn-ID", + "ktu": "ktu-Latn-CD", + "ktv": "ktv-Latn-VN", + "ktw": "ktw-Latn-US", + "ktx": "ktx-Latn-BR", + "kty": "kty-Latn-CD", + "ktz": "ktz-Latn-NA", + "ku": "ku-Latn-TR", + "ku-Arab": "ku-Arab-IQ", + "ku-LB": "ku-Arab-LB", + "ku-Yezi": "ku-Yezi-GE", + "kub": "kub-Latn-ZZ", + "kuc": "kuc-Latn-ID", + "kud": "kud-Latn-ZZ", + "kue": "kue-Latn-ZZ", + "kuf": "kuf-Laoo-LA", + "kug": "kug-Latn-NG", + "kuh": "kuh-Latn-NG", + "kui": "kui-Latn-BR", + "kuj": "kuj-Latn-ZZ", + "kuk": "kuk-Latn-ID", + "kul": "kul-Latn-NG", + "kum": "kum-Cyrl-RU", + "kun": "kun-Latn-ZZ", + "kuo": "kuo-Latn-PG", + "kup": "kup-Latn-ZZ", + "kuq": "kuq-Latn-BR", + "kus": "kus-Latn-ZZ", + "kut": "kut-Latn-CA", + "kuu": "kuu-Latn-US", + "kuv": "kuv-Latn-ID", + "kuw": "kuw-Latn-CF", + "kux": "kux-Latn-AU", + "kuy": "kuy-Latn-AU", + "kuz": "kuz-Latn-CL", + "kv": "kv-Cyrl-RU", + "kva": "kva-Cyrl-RU", + "kvb": "kvb-Latn-ID", + "kvc": "kvc-Latn-PG", + "kvd": "kvd-Latn-ID", + "kve": "kve-Latn-MY", + "kvf": "kvf-Latn-TD", + "kvg": "kvg-Latn-ZZ", + "kvh": "kvh-Latn-ID", + "kvi": "kvi-Latn-TD", + "kvj": "kvj-Latn-CM", + "kvl": "kvl-Latn-MM", + "kvm": "kvm-Latn-CM", + "kvn": "kvn-Latn-CO", + "kvo": "kvo-Latn-ID", + "kvp": "kvp-Latn-ID", + "kvq": "kvq-Mymr-MM", + "kvq-Latn": "kvq-Latn-MM", + "kvr": "kvr-Latn-ID", + "kvt": "kvt-Mymr-MM", + "kvv": "kvv-Latn-ID", + "kvw": "kvw-Latn-ID", + "kvx": "kvx-Arab-PK", + "kvy": "kvy-Kali-MM", + "kvz": "kvz-Latn-ID", + "kw": "kw-Latn-GB", + "kwa": "kwa-Latn-BR", + "kwb": "kwb-Latn-NG", + "kwc": "kwc-Latn-CG", + "kwd": "kwd-Latn-SB", + "kwe": "kwe-Latn-ID", + "kwf": "kwf-Latn-SB", + "kwg": "kwg-Latn-TD", + "kwh": "kwh-Latn-ID", + "kwi": "kwi-Latn-CO", + "kwj": "kwj-Latn-ZZ", + "kwk": "kwk-Latn-CA", + "kwl": "kwl-Latn-NG", + "kwm": "kwm-Latn-NA", + "kwn": "kwn-Latn-NA", + "kwo": "kwo-Latn-ZZ", + "kwp": "kwp-Latn-CI", + "kwq": "yam-Latn-ZZ", + "kwr": "kwr-Latn-ID", + "kws": "kws-Latn-CD", + "kwt": "kwt-Latn-ID", + "kwu": "kwu-Latn-CM", + "kwv": "kwv-Latn-TD", + "kww": "kww-Latn-SR", + "kwy": "kwy-Latn-CD", + "kwz": "kwz-Latn-AO", + "kxa": "kxa-Latn-ZZ", + "kxb": "kxb-Latn-CI", + "kxc": "kxc-Ethi-ZZ", + "kxd": "kxd-Latn-BN", + "kxd-Arab": "kxd-Arab-BN", + "kxe": "tvd-Latn-ZZ", + "kxf": "kxf-Mymr-MM", + "kxf-Latn": "kxf-Latn-MM", + "kxi": "kxi-Latn-MY", + "kxj": "kxj-Latn-TD", + "kxk": "kxk-Mymr-MM", + "kxl": "kru-Deva-IN", + "kxm": "kxm-Thai-TH", + "kxn": "kxn-Latn-MY", + "kxo": "kxo-Latn-BR", + "kxp": "kxp-Arab-PK", + "kxq": "kxq-Latn-ID", + "kxr": "kxr-Latn-PG", + "kxt": "kxt-Latn-PG", + "kxv": "kxv-Orya-IN", + "kxv-Latn": "kxv-Latn-IN", + "kxv-Telu": "kxv-Telu-IN", + "kxw": "kxw-Latn-ZZ", + "kxx": "kxx-Latn-CG", + "kxy": "kxy-Latn-VN", + "kxz": "kxz-Latn-ZZ", + "ky": "ky-Cyrl-KG", + "ky-Arab": "ky-Arab-CN", + "ky-CN": "ky-Arab-CN", + "ky-Latn": "ky-Latn-TR", + "ky-TR": "ky-Latn-TR", + "kya": "kya-Latn-TZ", + "kyb": "kyb-Latn-PH", + "kyc": "kyc-Latn-PG", + "kyd": "kyd-Latn-ID", + "kye": "kye-Latn-ZZ", + "kyf": "kyf-Latn-CI", + "kyg": "kyg-Latn-PG", + "kyh": "kyh-Latn-US", + "kyi": "kyi-Latn-MY", + "kyj": "kyj-Latn-PH", + "kyk": "kyk-Latn-PH", + "kyl": "kyl-Latn-US", + "kym": "kym-Latn-CF", + "kyn": "kyn-Latn-PH", + "kyo": "kyo-Latn-ID", + "kyq": "kyq-Latn-TD", + "kyr": "kyr-Latn-BR", + "kys": "kys-Latn-MY", + "kyt": "kyt-Latn-ID", + "kyu": "kyu-Kali-MM", + "kyu-Latn": "kyu-Latn-MM", + "kyu-Mymr": "kyu-Mymr-MM", + "kyv": "kyv-Deva-NP", + "kyw": "kyw-Deva-IN", + "kyw-Beng": "kyw-Beng-IN", + "kyw-Orya": "kyw-Orya-IN", + "kyx": "kyx-Latn-ZZ", + "kyy": "kyy-Latn-PG", + "kyz": "kyz-Latn-BR", + "kza": "kza-Latn-BF", + "kzb": "kzb-Latn-ID", + "kzc": "kzc-Latn-CI", + "kzd": "kzd-Latn-ID", + "kze": "kze-Latn-PG", + "kzf": "kzf-Latn-ID", + "kzh": "dgl-Arab-ZZ", + "kzi": "kzi-Latn-MY", + "kzj": "dtp-Latn-MY", + "kzk": "kzk-Latn-SB", + "kzl": "kzl-Latn-ID", + "kzm": "kzm-Latn-ID", + "kzn": "kzn-Latn-MW", + "kzo": "kzo-Latn-GA", + "kzp": "kzp-Latn-ID", + "kzr": "kzr-Latn-ZZ", + "kzs": "kzs-Latn-MY", + "kzt": "dtp-Latn-MY", + "kzu": "kzu-Latn-ID", + "kzv": "kzv-Latn-ID", + "kzw": "kzw-Latn-BR", + "kzx": "kzx-Latn-ID", + "kzy": "kzy-Latn-CD", + "kzz": "kzz-Latn-ID", + "la": "la-Latn-VA", + "laa": "laa-Latn-PH", + "lab": "lab-Lina-GR", + "lac": "lac-Latn-MX", + "lad": "lad-Hebr-IL", + "lae": "lae-Deva-IN", + "lae-Tibt": "lae-Tibt-IN", + "lag": "lag-Latn-TZ", + "lah": "lah-Arab-PK", + "lai": "lai-Latn-MW", + "laj": "laj-Latn-UG", + "lal": "lal-Latn-CD", + "lam": "lam-Latn-ZM", + "lan": "lan-Latn-NG", + "lap": "lap-Latn-TD", + "laq": "laq-Latn-VN", + "lar": "lar-Latn-GH", + "las": "las-Latn-ZZ", + "lau": "lau-Latn-ID", + "law": "law-Latn-ID", + "lax": "lax-Latn-IN", + "lax-Beng": "lax-Beng-IN", + "laz": "laz-Latn-PG", + "lb": "lb-Latn-LU", + "lbb": "lbb-Latn-PG", + "lbc": "lbc-Lisu-CN", + "lbe": "lbe-Cyrl-RU", + "lbf": "lbf-Deva-IN", + "lbf-Tibt": "lbf-Tibt-CN", + "lbi": "lbi-Latn-CM", + "lbj": "lbj-Tibt-IN", + "lbj-Arab": "lbj-Arab-IN", + "lbl": "lbl-Latn-PH", + "lbm": "lbm-Deva-IN", + "lbn": "lbn-Latn-LA", + "lbn-Laoo": "lbn-Laoo-LA", + "lbo": "lbo-Laoo-LA", + "lbo-Latn": "lbo-Latn-US", + "lbq": "lbq-Latn-PG", + "lbr": "lbr-Deva-NP", + "lbt": "lbt-Latn-VN", + "lbu": "lbu-Latn-ZZ", + "lbv": "lbv-Latn-PG", + "lbw": "lbw-Latn-ID", + "lbx": "lbx-Latn-ID", + "lby": "lby-Latn-AU", + "lbz": "lbz-Latn-AU", + "lcc": "lcc-Latn-ID", + "lcd": "lcd-Latn-ID", + "lce": "lce-Latn-ID", + "lcf": "lcf-Latn-ID", + "lch": "lch-Latn-AO", + "lcl": "lcl-Latn-ID", + "lcm": "lcm-Latn-ZZ", + "lcp": "lcp-Thai-CN", + "lcq": "lcq-Latn-ID", + "lcs": "lcs-Latn-ID", + "lda": "lda-Latn-CI", + "ldb": "ldb-Latn-ZZ", + "ldd": "ldd-Latn-NG", + "ldg": "ldg-Latn-NG", + "ldh": "ldh-Latn-NG", + "ldi": "ldi-Latn-CG", + "ldj": "ldj-Latn-NG", + "ldk": "ldk-Latn-NG", + "ldl": "ldl-Latn-NG", + "ldm": "ldm-Latn-GN", + "ldn": "ldn-Latn-001", + "ldo": "ldo-Latn-NG", + "ldp": "ldp-Latn-NG", + "ldq": "ldq-Latn-NG", + "lea": "lea-Latn-CD", + "leb": "leb-Latn-ZM", + "lec": "lec-Latn-BO", + "led": "led-Latn-ZZ", + "lee": "lee-Latn-ZZ", + "lef": "lef-Latn-GH", + "leh": "leh-Latn-ZM", + "lei": "lei-Latn-PG", + "lej": "lej-Latn-CD", + "lek": "lek-Latn-PG", + "lel": "lel-Latn-CD", + "lem": "lem-Latn-ZZ", + "len": "len-Latn-HN", + "leo": "leo-Latn-CM", + "lep": "lep-Lepc-IN", + "leq": "leq-Latn-ZZ", + "ler": "ler-Latn-PG", + "les": "les-Latn-CD", + "let": "let-Latn-PG", + "leu": "leu-Latn-ZZ", + "lev": "lev-Latn-ID", + "lew": "lew-Latn-ID", + "lex": "lex-Latn-ID", + "ley": "ley-Latn-ID", + "lez": "lez-Cyrl-RU", + "lfa": "lfa-Latn-CM", + "lfn": "lfn-Latn-001", + "lfn-Cyrl": "lfn-Cyrl-001", + "lg": "lg-Latn-UG", + "lga": "lga-Latn-SB", + "lgb": "lgb-Latn-SB", + "lgg": "lgg-Latn-ZZ", + "lgh": "lgh-Latn-VN", + "lgi": "lgi-Latn-ID", + "lgk": "lgk-Latn-VU", + "lgl": "lgl-Latn-SB", + "lgm": "lgm-Latn-CD", + "lgn": "lgn-Latn-ET", + "lgo": "lgo-Latn-SS", + "lgq": "lgq-Latn-GH", + "lgr": "lgr-Latn-SB", + "lgt": "lgt-Latn-PG", + "lgu": "lgu-Latn-SB", + "lgz": "lgz-Latn-CD", + "lha": "lha-Latn-VN", + "lhh": "lhh-Latn-ID", + "lhi": "lhi-Latn-CN", + "lhm": "lhm-Deva-NP", + "lhn": "lhn-Latn-MY", + "lhs": "lhs-Syrc-SY", + "lht": "lht-Latn-VU", + "lhu": "lhu-Latn-CN", + "li": "li-Latn-NL", + "lia": "lia-Latn-ZZ", + "lib": "lib-Latn-PG", + "lic": "lic-Latn-CN", + "lid": "lid-Latn-ZZ", + "lie": "lie-Latn-CD", + "lif": "lif-Deva-NP", + "lif-Limb": "lif-Limb-IN", + "lig": "lig-Latn-ZZ", + "lih": "lih-Latn-ZZ", + "lij": "lij-Latn-IT", + "lik": "lik-Latn-CD", + "lil": "lil-Latn-CA", + "lio": "lio-Latn-ID", + "lip": "lip-Latn-GH", + "liq": "liq-Latn-ET", + "lir": "lir-Latn-LR", + "lis": "lis-Lisu-CN", + "liu": "liu-Latn-SD", + "liv": "liv-Latn-LV", + "liw": "liw-Latn-ID", + "lix": "lix-Latn-ID", + "liy": "liy-Latn-CF", + "liz": "liz-Latn-CD", + "lja": "lja-Latn-AU", + "lje": "lje-Latn-ID", + "lji": "lji-Latn-ID", + "ljl": "ljl-Latn-ID", + "ljp": "ljp-Latn-ID", + "ljw": "ljw-Latn-AU", + "ljx": "ljx-Latn-AU", + "lka": "lka-Latn-TL", + "lkb": "lkb-Latn-KE", + "lkc": "lkc-Latn-VN", + "lkd": "lkd-Latn-BR", + "lke": "lke-Latn-UG", + "lkh": "lkh-Tibt-BT", + "lki": "lki-Arab-IR", + "lkj": "lkj-Latn-MY", + "lkl": "lkl-Latn-PG", + "lkm": "lkm-Latn-AU", + "lkn": "lkn-Latn-VU", + "lko": "lko-Latn-KE", + "lkr": "lkr-Latn-SS", + "lks": "lks-Latn-KE", + "lkt": "lkt-Latn-US", + "lku": "lku-Latn-AU", + "lky": "lky-Latn-SS", + "lla": "lla-Latn-NG", + "llb": "llb-Latn-MZ", + "llc": "llc-Latn-GN", + "lld": "lld-Latn-IT", + "lle": "lle-Latn-ZZ", + "llf": "llf-Latn-PG", + "llg": "llg-Latn-ID", + "lli": "lli-Latn-CG", + "llj": "llj-Latn-AU", + "llk": "llk-Latn-MY", + "lll": "lll-Latn-PG", + "llm": "llm-Latn-ID", + "lln": "lln-Latn-ZZ", + "llp": "llp-Latn-VU", + "llq": "llq-Latn-ID", + "llu": "llu-Latn-SB", + "llx": "llx-Latn-FJ", + "lma": "lma-Latn-GN", + "lmb": "lmb-Latn-VU", + "lmc": "lmc-Latn-AU", + "lmd": "lmd-Latn-SD", + "lme": "lme-Latn-TD", + "lmf": "lmf-Latn-ID", + "lmg": "lmg-Latn-PG", + "lmh": "lmh-Deva-NP", + "lmi": "lmi-Latn-CD", + "lmj": "lmj-Latn-ID", + "lmk": "lmk-Latn-IN", + "lmk-Mymr": "lmk-Mymr-IN", + "lml": "lml-Latn-VU", + "lmn": "lmn-Telu-IN", + "lmo": "lmo-Latn-IT", + "lmp": "lmp-Latn-ZZ", + "lmq": "lmq-Latn-ID", + "lmr": "lmr-Latn-ID", + "lmu": "lmu-Latn-VU", + "lmv": "lmv-Latn-FJ", + "lmw": "lmw-Latn-US", + "lmx": "lmx-Latn-CM", + "lmy": "lmy-Latn-ID", + "ln": "ln-Latn-CD", + "lna": "lna-Latn-CF", + "lnb": "lnb-Latn-NA", + "lnd": "lnd-Latn-ID", + "lnh": "lnh-Latn-MY", + "lni": "lni-Latn-PG", + "lnj": "lnj-Latn-AU", + "lnl": "lnl-Latn-CF", + "lnm": "lnm-Latn-PG", + "lnn": "lnn-Latn-VU", + "lns": "lns-Latn-ZZ", + "lnu": "lnu-Latn-ZZ", + "lnw": "lnw-Latn-AU", + "lnz": "lnz-Latn-CD", + "lo": "lo-Laoo-LA", + "loa": "loa-Latn-ID", + "lob": "lob-Latn-BF", + "loc": "loc-Latn-PH", + "loe": "loe-Latn-ID", + "log": "log-Latn-CD", + "loh": "loh-Latn-SS", + "loi": "loi-Latn-CI", + "loj": "loj-Latn-ZZ", + "lok": "lok-Latn-ZZ", + "lol": "lol-Latn-CD", + "lom": "lom-Latn-LR", + "lon": "lon-Latn-MW", + "loo": "loo-Latn-CD", + "lop": "lop-Latn-NG", + "loq": "loq-Latn-CD", + "lor": "lor-Latn-ZZ", + "los": "los-Latn-ZZ", + "lot": "lot-Latn-SS", + "lot-Arab": "lot-Arab-SS", + "lou": "lou-Latn-US", + "low": "low-Latn-MY", + "lox": "lox-Latn-ID", + "loy": "loy-Deva-NP", + "loy-Tibt": "loy-Tibt-NP", + "loz": "loz-Latn-ZM", + "lpa": "lpa-Latn-VU", + "lpe": "lpe-Latn-ID", + "lpn": "lpn-Latn-MM", + "lpo": "lpo-Plrd-CN", + "lpo-Lisu": "lpo-Lisu-CN", + "lpx": "lpx-Latn-SS", + "lqr": "lqr-Latn-SS", + "lra": "lra-Latn-MY", + "lrc": "lrc-Arab-IR", + "lrg": "lrg-Latn-AU", + "lri": "lri-Latn-KE", + "lrk": "lrk-Arab-PK", + "lrl": "lrl-Arab-IR", + "lrm": "lrm-Latn-KE", + "lrn": "lrn-Latn-ID", + "lro": "lro-Latn-SD", + "lrt": "lrt-Latn-ID", + "lrv": "lrv-Latn-VU", + "lrz": "lrz-Latn-VU", + "lsa": "lsa-Arab-IR", + "lsd": "lsd-Hebr-IL", + "lse": "lse-Latn-CD", + "lsi": "lsi-Latn-MM", + "lsm": "lsm-Latn-UG", + "lsr": "lsr-Latn-PG", + "lss": "lss-Arab-PK", + "lt": "lt-Latn-LT", + "ltg": "ltg-Latn-LV", + "lth": "lth-Latn-UG", + "lti": "lti-Latn-ID", + "ltn": "ltn-Latn-BR", + "lto": "lto-Latn-KE", + "lts": "lts-Latn-KE", + "ltu": "ltu-Latn-ID", + "lu": "lu-Latn-CD", + "lua": "lua-Latn-CD", + "luc": "luc-Latn-UG", + "lud": "lud-Latn-RU", + "lue": "lue-Latn-ZM", + "luf": "luf-Latn-PG", + "lui": "lui-Latn-US", + "luj": "luj-Latn-CD", + "luk": "luk-Tibt-BT", + "lul": "lul-Latn-SS", + "lum": "lum-Latn-AO", + "lun": "lun-Latn-ZM", + "luo": "luo-Latn-KE", + "lup": "lup-Latn-GA", + "luq": "luq-Latn-CU", + "lur": "lur-Latn-ID", + "lus": "lus-Latn-IN", + "lus-Beng": "lus-Beng-BD", + "lus-Brai": "lus-Brai-IN", + "lut": "lut-Latn-US", + "luu": "luu-Deva-NP", + "luv": "luv-Arab-OM", + "luw": "luw-Latn-CM", + "luy": "luy-Latn-KE", + "luz": "luz-Arab-IR", + "lv": "lv-Latn-LV", + "lva": "lva-Latn-TL", + "lvi": "lvi-Latn-LA", + "lvk": "lvk-Latn-SB", + "lvu": "lvu-Latn-ID", + "lwa": "lwa-Latn-CD", + "lwe": "lwe-Latn-ID", + "lwg": "lwg-Latn-KE", + "lwh": "lwh-Latn-VN", + "lwl": "lwl-Thai-TH", + "lwm": "lwm-Thai-CN", + "lwo": "lwo-Latn-SS", + "lwo-ZA": "lwo-Latn-ZA", + "lwt": "lwt-Latn-ID", + "lww": "lww-Latn-VU", + "lxm": "lxm-Latn-PG", + "lya": "lya-Tibt-BT", + "lyn": "lyn-Latn-ZM", + "lzh": "lzh-Hans-CN", + "lzl": "lzl-Latn-VU", + "lzn": "lzn-Latn-MM", + "lzz": "lzz-Latn-TR", + "maa": "maa-Latn-MX", + "mab": "mab-Latn-MX", + "mad": "mad-Latn-ID", + "mae": "mae-Latn-NG", + "maf": "maf-Latn-CM", + "mag": "mag-Deva-IN", + "mai": "mai-Deva-IN", + "maj": "maj-Latn-MX", + "mak": "mak-Latn-ID", + "mam": "mam-Latn-GT", + "man": "man-Latn-GM", + "man-GN": "man-Nkoo-GN", + "man-Nkoo": "man-Nkoo-GN", + "maq": "maq-Latn-MX", + "mas": "mas-Latn-KE", + "mat": "mat-Latn-MX", + "mau": "mau-Latn-MX", + "mav": "mav-Latn-BR", + "maw": "maw-Latn-ZZ", + "max": "max-Latn-ID", + "maz": "maz-Latn-MX", + "mba": "mba-Latn-PH", + "mbb": "mbb-Latn-PH", + "mbc": "mbc-Latn-BR", + "mbd": "mbd-Latn-PH", + "mbf": "mbf-Latn-SG", + "mbh": "mbh-Latn-ZZ", + "mbi": "mbi-Latn-PH", + "mbj": "mbj-Latn-BR", + "mbk": "mbk-Latn-PG", + "mbl": "mbl-Latn-BR", + "mbm": "mbm-Latn-CG", + "mbn": "mbn-Latn-CO", + "mbo": "mbo-Latn-ZZ", + "mbp": "mbp-Latn-CO", + "mbq": "mbq-Latn-ZZ", + "mbr": "mbr-Latn-CO", + "mbs": "mbs-Latn-PH", + "mbt": "mbt-Latn-PH", + "mbu": "mbu-Latn-ZZ", + "mbv": "mbv-Latn-GN", + "mbw": "mbw-Latn-ZZ", + "mbx": "mbx-Latn-PG", + "mby": "mby-Arab-PK", + "mbz": "mbz-Latn-MX", + "mca": "mca-Latn-PY", + "mcb": "mcb-Latn-PE", + "mcc": "mcc-Latn-PG", + "mcd": "mcd-Latn-PE", + "mce": "mce-Latn-MX", + "mcf": "mcf-Latn-PE", + "mcg": "mcg-Latn-VE", + "mch": "mch-Latn-VE", + "mci": "mci-Latn-ZZ", + "mcj": "mcj-Latn-NG", + "mck": "mck-Latn-AO", + "mcl": "mcl-Latn-CO", + "mcm": "mcm-Latn-MY", + "mcn": "mcn-Latn-TD", + "mco": "mco-Latn-MX", + "mcp": "mcp-Latn-ZZ", + "mcq": "mcq-Latn-ZZ", + "mcr": "mcr-Latn-ZZ", + "mcs": "mcs-Latn-CM", + "mct": "mct-Latn-CM", + "mcu": "mcu-Latn-ZZ", + "mcv": "mcv-Latn-PG", + "mcw": "mcw-Latn-TD", + "mcx": "mcx-Latn-CF", + "mcy": "mcy-Latn-PG", + "mcz": "mcz-Latn-PG", + "mda": "mda-Latn-ZZ", + "mdb": "mdb-Latn-PG", + "mdc": "mdc-Latn-PG", + "mdd": "mdd-Latn-CM", + "mde": "mde-Arab-ZZ", + "mdf": "mdf-Cyrl-RU", + "mdg": "mdg-Latn-TD", + "mdh": "mdh-Latn-PH", + "mdi": "mdi-Latn-CD", + "mdj": "mdj-Latn-ZZ", + "mdk": "mdk-Latn-CD", + "mdm": "mdm-Latn-CD", + "mdn": "mdn-Latn-CF", + "mdp": "mdp-Latn-CD", + "mdq": "mdq-Latn-CD", + "mdr": "mdr-Latn-ID", + "mds": "mds-Latn-PG", + "mdt": "mdt-Latn-CG", + "mdu": "mdu-Latn-CG", + "mdv": "mdv-Latn-MX", + "mdw": "mdw-Latn-CG", + "mdx": "mdx-Ethi-ZZ", + "mdy": "mdy-Ethi-ET", + "mdy-Latn": "mdy-Latn-ET", + "mdz": "mdz-Latn-BR", + "mea": "mea-Latn-CM", + "meb": "meb-Latn-PG", + "mec": "mec-Latn-AU", + "med": "med-Latn-ZZ", + "mee": "mee-Latn-ZZ", + "meh": "meh-Latn-MX", + "mej": "mej-Latn-ID", + "mek": "mek-Latn-ZZ", + "mel": "mel-Latn-MY", + "mem": "mem-Latn-AU", + "men": "men-Latn-SL", + "meo": "meo-Latn-MY", + "meo-Arab": "meo-Arab-MY", + "mep": "mep-Latn-AU", + "meq": "meq-Latn-CM", + "mer": "mer-Latn-KE", + "mes": "mes-Latn-TD", + "met": "met-Latn-ZZ", + "meu": "meu-Latn-ZZ", + "mev": "mev-Latn-LR", + "mew": "mew-Latn-NG", + "mey": "mey-Latn-MR", + "mey-Arab": "mey-Arab-MR", + "mez": "mez-Latn-US", + "mfa": "mfa-Arab-TH", + "mfb": "mfb-Latn-ID", + "mfc": "mfc-Latn-CD", + "mfd": "mfd-Latn-CM", + "mfe": "mfe-Latn-MU", + "mff": "mff-Latn-CM", + "mfg": "mfg-Latn-GN", + "mfg-Arab": "mfg-Arab-GN", + "mfh": "mfh-Latn-CM", + "mfi": "mfi-Arab-CM", + "mfi-Latn": "mfi-Latn-CM", + "mfj": "mfj-Latn-CM", + "mfk": "mfk-Latn-CM", + "mfl": "mfl-Latn-NG", + "mfm": "mfm-Latn-NG", + "mfn": "mfn-Latn-ZZ", + "mfo": "mfo-Latn-ZZ", + "mfp": "mfp-Latn-ID", + "mfq": "mfq-Latn-ZZ", + "mfr": "mfr-Latn-AU", + "mft": "mft-Latn-PG", + "mfu": "mfu-Latn-AO", + "mfv": "mfv-Latn-GW", + "mfw": "mfw-Latn-PG", + "mfx": "mfx-Latn-ET", + "mfx-Ethi": "mfx-Ethi-ET", + "mfy": "mfy-Latn-MX", + "mfz": "mfz-Latn-SS", + "mg": "mg-Latn-MG", + "mgb": "mgb-Latn-TD", + "mgc": "mgc-Latn-SS", + "mgd": "mgd-Latn-SS", + "mgd-Arab": "mgd-Arab-SS", + "mge": "mge-Latn-TD", + "mgf": "mgf-Latn-ID", + "mgg": "mgg-Latn-CM", + "mgh": "mgh-Latn-MZ", + "mgi": "mgi-Latn-NG", + "mgj": "mgj-Latn-NG", + "mgk": "mgk-Latn-ID", + "mgl": "mgl-Latn-ZZ", + "mgm": "mgm-Latn-TL", + "mgn": "mgn-Latn-CF", + "mgo": "mgo-Latn-CM", + "mgp": "mgp-Deva-NP", + "mgq": "mgq-Latn-TZ", + "mgr": "mgr-Latn-ZM", + "mgs": "mgs-Latn-TZ", + "mgt": "mgt-Latn-PG", + "mgu": "mgu-Latn-PG", + "mgv": "mgv-Latn-TZ", + "mgw": "mgw-Latn-TZ", + "mgy": "mgy-Latn-TZ", + "mgz": "mgz-Latn-TZ", + "mh": "mh-Latn-MH", + "mhb": "mhb-Latn-GA", + "mhc": "mhc-Latn-MX", + "mhd": "mhd-Latn-TZ", + "mhe": "mhe-Latn-MY", + "mhf": "mhf-Latn-PG", + "mhg": "mhg-Latn-AU", + "mhi": "mhi-Latn-ZZ", + "mhj": "mhj-Arab-AF", + "mhk": "mhk-Latn-CM", + "mhl": "mhl-Latn-ZZ", + "mhm": "mhm-Latn-MZ", + "mhn": "mhn-Latn-IT", + "mho": "mho-Latn-ZM", + "mhp": "mhp-Latn-ID", + "mhq": "mhq-Latn-US", + "mhs": "mhs-Latn-ID", + "mht": "mht-Latn-VE", + "mhu": "mhu-Latn-IN", + "mhw": "mhw-Latn-BW", + "mhx": "mhx-Latn-MM", + "mhy": "mhy-Latn-ID", + "mhz": "mhz-Latn-ID", + "mi": "mi-Latn-NZ", + "mia": "mia-Latn-US", + "mib": "mib-Latn-MX", + "mic": "mic-Latn-CA", + "mid": "mid-Mand-IQ", + "mie": "mie-Latn-MX", + "mif": "mif-Latn-ZZ", + "mig": "mig-Latn-MX", + "mih": "mih-Latn-MX", + "mii": "mii-Latn-MX", + "mij": "mij-Latn-CM", + "mik": "mik-Latn-US", + "mil": "mil-Latn-MX", + "mim": "mim-Latn-MX", + "min": "min-Latn-ID", + "mio": "mio-Latn-MX", + "mip": "mip-Latn-MX", + "miq": "miq-Latn-NI", + "mir": "mir-Latn-MX", + "mit": "mit-Latn-MX", + "miu": "miu-Latn-MX", + "miw": "miw-Latn-ZZ", + "mix": "mix-Latn-MX", + "miy": "miy-Latn-MX", + "miz": "miz-Latn-MX", + "mjb": "mjb-Latn-TL", + "mjc": "mjc-Latn-MX", + "mjd": "mjd-Latn-US", + "mje": "mje-Latn-TD", + "mjg": "mjg-Latn-CN", + "mjh": "mjh-Latn-TZ", + "mji": "mji-Latn-CN", + "mjj": "mjj-Latn-PG", + "mjk": "mjk-Latn-PG", + "mjl": "mjl-Deva-IN", + "mjl-Takr": "mjl-Takr-IN", + "mjm": "mjm-Latn-PG", + "mjn": "mjn-Latn-PG", + "mjq": "mjq-Mlym-IN", + "mjr": "mjr-Mlym-IN", + "mjs": "mjs-Latn-NG", + "mjt": "mjt-Deva-IN", + "mjt-Beng": "mjt-Beng-BD", + "mju": "mju-Telu-IN", + "mjv": "mjv-Mlym-IN", + "mjw": "mjw-Latn-IN", + "mjx": "mjx-Latn-BD", + "mjx-Beng": "mjx-Beng-BD", + "mjy": "mjy-Latn-US", + "mjz": "mjz-Deva-NP", + "mk": "mk-Cyrl-MK", + "mka": "mka-Latn-CI", + "mkb": "mkb-Deva-IN", + "mkc": "mkc-Latn-PG", + "mke": "mke-Deva-IN", + "mkf": "mkf-Latn-NG", + "mki": "mki-Arab-ZZ", + "mkj": "mkj-Latn-FM", + "mkk": "mkk-Latn-CM", + "mkl": "mkl-Latn-ZZ", + "mkm": "mkm-Thai-TH", + "mkn": "mkn-Latn-ID", + "mko": "mko-Latn-NG", + "mkp": "mkp-Latn-ZZ", + "mkr": "mkr-Latn-PG", + "mks": "mks-Latn-MX", + "mkt": "mkt-Latn-NC", + "mku": "mku-Latn-GN", + "mkv": "mkv-Latn-VU", + "mkw": "mkw-Latn-ZZ", + "mkx": "mkx-Latn-PH", + "mky": "mky-Latn-ID", + "mkz": "mkz-Latn-TL", + "ml": "ml-Mlym-IN", + "mla": "mla-Latn-VU", + "mlb": "mlb-Latn-CM", + "mlc": "mlc-Latn-VN", + "mle": "mle-Latn-ZZ", + "mlf": "mlf-Thai-LA", + "mlf-Latn": "mlf-Latn-LA", + "mlh": "mlh-Latn-PG", + "mli": "mli-Latn-ID", + "mlj": "mlj-Latn-TD", + "mlk": "mlk-Latn-KE", + "mll": "mll-Latn-VU", + "mln": "mln-Latn-SB", + "mlo": "mlo-Latn-SN", + "mlp": "mlp-Latn-ZZ", + "mlq": "mlq-Latn-SN", + "mlq-Arab": "mlq-Arab-SN", + "mlr": "mlr-Latn-CM", + "mls": "mls-Latn-SD", + "mlu": "mlu-Latn-SB", + "mlv": "mlv-Latn-VU", + "mlw": "mlw-Latn-CM", + "mlx": "mlx-Latn-VU", + "mlz": "mlz-Latn-PH", + "mma": "mma-Latn-NG", + "mmb": "mmb-Latn-ID", + "mmc": "mmc-Latn-MX", + "mmd": "mmd-Latn-CN", + "mmd-Hans": "mmd-Hans-CN", + "mmd-Hant": "mmd-Hant-CN", + "mme": "mme-Latn-VU", + "mmf": "mmf-Latn-NG", + "mmg": "mmg-Latn-VU", + "mmh": "mmh-Latn-BR", + "mmi": "mmi-Latn-PG", + "mmm": "mmm-Latn-VU", + "mmn": "mmn-Latn-PH", + "mmo": "mmo-Latn-ZZ", + "mmp": "mmp-Latn-PG", + "mmq": "mmq-Latn-PG", + "mmr": "mmr-Latn-CN", + "mmt": "mmt-Latn-PG", + "mmu": "mmu-Latn-ZZ", + "mmv": "mmv-Latn-BR", + "mmw": "mmw-Latn-VU", + "mmx": "mmx-Latn-ZZ", + "mmy": "mmy-Latn-TD", + "mmz": "mmz-Latn-CD", + "mn": "mn-Cyrl-MN", + "mn-CN": "mn-Mong-CN", + "mn-Mong": "mn-Mong-CN", + "mna": "mna-Latn-ZZ", + "mnb": "mnb-Latn-ID", + "mnd": "mnd-Latn-BR", + "mne": "mne-Latn-TD", + "mnf": "mnf-Latn-ZZ", + "mng": "mng-Latn-VN", + "mnh": "mnh-Latn-CD", + "mni": "mni-Beng-IN", + "mnj": "mnj-Arab-AF", + "mnl": "mnl-Latn-VU", + "mnm": "mnm-Latn-PG", + "mnn": "mnn-Latn-VN", + "mnp": "mnp-Latn-CN", + "mnq": "mnq-Latn-MY", + "mnr": "mnr-Latn-US", + "mns": "mns-Cyrl-RU", + "mnu": "mnu-Latn-ID", + "mnv": "mnv-Latn-SB", + "mnw": "mnw-Mymr-MM", + "mnx": "mnx-Latn-ID", + "mny": "mny-Latn-MZ", + "mnz": "mnz-Latn-ID", + "mo": "ro-Latn-RO", + "moa": "moa-Latn-ZZ", + "moc": "moc-Latn-AR", + "mod": "mod-Latn-US", + "moe": "moe-Latn-CA", + "mog": "mog-Latn-ID", + "moh": "moh-Latn-CA", + "moi": "moi-Latn-NG", + "moj": "moj-Latn-CG", + "mok": "mok-Latn-ID", + "mom": "mom-Latn-NI", + "moo": "moo-Latn-VN", + "mop": "mop-Latn-BZ", + "moq": "moq-Latn-ID", + "mor": "mor-Latn-SD", + "mos": "mos-Latn-BF", + "mot": "mot-Latn-CO", + "mou": "mou-Latn-TD", + "mov": "mov-Latn-US", + "mow": "mow-Latn-CG", + "mox": "mox-Latn-ZZ", + "moy": "moy-Latn-ET", + "moy-Ethi": "moy-Ethi-ET", + "moz": "moz-Latn-TD", + "mpa": "mpa-Latn-TZ", + "mpb": "mpb-Latn-AU", + "mpc": "mpc-Latn-AU", + "mpd": "mpd-Latn-BR", + "mpe": "mpe-Latn-ET", + "mpe-Ethi": "mpe-Ethi-ET", + "mpg": "mpg-Latn-TD", + "mph": "mph-Latn-AU", + "mpi": "mpi-Latn-CM", + "mpj": "mpj-Latn-AU", + "mpk": "mpk-Latn-TD", + "mpl": "mpl-Latn-PG", + "mpm": "mpm-Latn-MX", + "mpn": "mpn-Latn-PG", + "mpo": "mpo-Latn-PG", + "mpp": "mpp-Latn-ZZ", + "mpq": "mpq-Latn-BR", + "mpr": "mpr-Latn-SB", + "mps": "mps-Latn-ZZ", + "mpt": "mpt-Latn-ZZ", + "mpu": "mpu-Latn-BR", + "mpv": "mpv-Latn-PG", + "mpw": "mpw-Latn-BR", + "mpx": "mpx-Latn-ZZ", + "mpy": "mpy-Latn-ID", + "mpz": "mpz-Thai-TH", + "mqa": "mqa-Latn-ID", + "mqb": "mqb-Latn-CM", + "mqc": "mqc-Latn-ID", + "mqe": "mqe-Latn-PG", + "mqf": "mqf-Latn-ID", + "mqg": "mqg-Latn-ID", + "mqh": "mqh-Latn-MX", + "mqi": "mqi-Latn-ID", + "mqj": "mqj-Latn-ID", + "mqk": "mqk-Latn-PH", + "mql": "mql-Latn-ZZ", + "mqm": "mqm-Latn-PF", + "mqn": "mqn-Latn-ID", + "mqo": "mqo-Latn-ID", + "mqp": "mqp-Latn-ID", + "mqq": "mqq-Latn-MY", + "mqr": "mqr-Latn-ID", + "mqs": "mqs-Latn-ID", + "mqu": "mqu-Latn-SS", + "mqv": "mqv-Latn-PG", + "mqw": "mqw-Latn-PG", + "mqx": "mqx-Latn-ID", + "mqx-Bugi": "mqx-Bugi-ID", + "mqy": "mqy-Latn-ID", + "mqz": "mqz-Latn-PG", + "mr": "mr-Deva-IN", + "mra": "mra-Thai-TH", + "mrb": "mrb-Latn-VU", + "mrc": "mrc-Latn-US", + "mrd": "mrd-Deva-NP", + "mrf": "mrf-Latn-ID", + "mrg": "mrg-Latn-IN", + "mrg-Beng": "mrg-Beng-IN", + "mrg-Deva": "mrg-Deva-IN", + "mrh": "mrh-Latn-IN", + "mrj": "mrj-Cyrl-RU", + "mrk": "mrk-Latn-NC", + "mrl": "mrl-Latn-FM", + "mrm": "mrm-Latn-VU", + "mrn": "mrn-Latn-SB", + "mro": "mro-Mroo-BD", + "mrp": "mrp-Latn-VU", + "mrq": "mrq-Latn-PF", + "mrr": "mrr-Deva-IN", + "mrs": "mrs-Latn-VU", + "mrt": "mrt-Latn-NG", + "mru": "mru-Latn-CM", + "mrv": "mrv-Latn-PF", + "mrw": "mrw-Latn-PH", + "mrw-Arab": "mrw-Arab-PH", + "mrx": "mrx-Latn-ID", + "mry": "mry-Latn-PH", + "mrz": "mrz-Latn-ID", + "ms": "ms-Latn-MY", + "ms-CC": "ms-Arab-CC", + "msb": "msb-Latn-PH", + "msc": "msc-Latn-GN", + "mse": "mse-Latn-TD", + "msf": "msf-Latn-ID", + "msg": "msg-Latn-ID", + "msh": "msh-Latn-MG", + "msi": "msi-Latn-MY", + "msj": "msj-Latn-CD", + "msk": "msk-Latn-PH", + "msl": "msl-Latn-ID", + "msm": "msm-Latn-PH", + "msn": "msn-Latn-VU", + "mso": "mso-Latn-ID", + "msp": "msp-Latn-BR", + "msq": "msq-Latn-NC", + "mss": "mss-Latn-ID", + "msu": "msu-Latn-PG", + "msv": "msv-Latn-CM", + "msw": "msw-Latn-GW", + "msx": "msx-Latn-PG", + "msy": "msy-Latn-PG", + "msz": "msz-Latn-PG", + "mt": "mt-Latn-MT", + "mta": "mta-Latn-PH", + "mtb": "mtb-Latn-CI", + "mtc": "mtc-Latn-ZZ", + "mtd": "mtd-Latn-ID", + "mte": "mte-Latn-SB", + "mtf": "mtf-Latn-ZZ", + "mtg": "mtg-Latn-ID", + "mth": "mth-Latn-ID", + "mti": "mti-Latn-ZZ", + "mtj": "mtj-Latn-ID", + "mtk": "mtk-Latn-CM", + "mtl": "mtl-Latn-NG", + "mtm": "mtm-Cyrl-RU", + "mtn": "mtn-Latn-NI", + "mto": "mto-Latn-MX", + "mtp": "mtp-Latn-BO", + "mtq": "mtq-Latn-VN", + "mtr": "mtr-Deva-IN", + "mts": "mts-Latn-PE", + "mtt": "mtt-Latn-VU", + "mtu": "mtu-Latn-MX", + "mtv": "mtv-Latn-PG", + "mtw": "mtw-Latn-PH", + "mtx": "mtx-Latn-MX", + "mty": "mty-Latn-PG", + "mua": "mua-Latn-CM", + "mub": "mub-Latn-TD", + "muc": "muc-Latn-CM", + "mud": "mud-Cyrl-RU", + "mue": "mue-Latn-EC", + "mug": "mug-Latn-CM", + "muh": "muh-Latn-SS", + "mui": "mui-Latn-ID", + "muj": "muj-Latn-TD", + "muk": "muk-Tibt-NP", + "mum": "mum-Latn-PG", + "muo": "muo-Latn-CM", + "muq": "muq-Latn-CN", + "mur": "mur-Latn-ZZ", + "mus": "mus-Latn-US", + "mut": "mut-Deva-IN", + "muu": "muu-Latn-KE", + "muv": "muv-Taml-IN", + "mux": "mux-Latn-PG", + "muy": "muy-Latn-CM", + "muz": "muz-Ethi-ET", + "muz-Latn": "muz-Latn-ET", + "mva": "mva-Latn-ZZ", + "mvd": "mvd-Latn-ID", + "mvf": "mvf-Mong-CN", + "mvf-Phag": "mvf-Phag-CN", + "mvg": "mvg-Latn-MX", + "mvh": "mvh-Latn-TD", + "mvk": "mvk-Latn-PG", + "mvl": "mvl-Latn-AU", + "mvn": "mvn-Latn-ZZ", + "mvo": "mvo-Latn-SB", + "mvp": "mvp-Latn-ID", + "mvq": "mvq-Latn-PG", + "mvr": "mvr-Latn-ID", + "mvs": "mvs-Latn-ID", + "mvt": "mvt-Latn-VU", + "mvu": "mvu-Latn-TD", + "mvv": "mvv-Latn-MY", + "mvw": "mvw-Latn-TZ", + "mvx": "mvx-Latn-ID", + "mvy": "mvy-Arab-PK", + "mvz": "mvz-Ethi-ET", + "mvz-Arab": "mvz-Arab-ET", + "mwa": "mwa-Latn-PG", + "mwb": "mwb-Latn-PG", + "mwc": "mwc-Latn-PG", + "mwe": "mwe-Latn-TZ", + "mwf": "mwf-Latn-AU", + "mwg": "mwg-Latn-PG", + "mwh": "mwh-Latn-PG", + "mwi": "mwi-Latn-VU", + "mwk": "mwk-Latn-ML", + "mwl": "mwl-Latn-PT", + "mwm": "mwm-Latn-TD", + "mwn": "mwn-Latn-ZM", + "mwo": "mwo-Latn-VU", + "mwp": "mwp-Latn-AU", + "mwq": "mwq-Latn-MM", + "mwr": "mwr-Deva-IN", + "mws": "mws-Latn-KE", + "mwt": "mwt-Mymr-MM", + "mwt-Thai": "mwt-Thai-TH", + "mwu": "mwu-Latn-SS", + "mwv": "mwv-Latn-ID", + "mww": "mww-Hmnp-US", + "mwz": "mwz-Latn-CD", + "mxa": "mxa-Latn-MX", + "mxb": "mxb-Latn-MX", + "mxc": "mxc-Latn-ZW", + "mxd": "mxd-Latn-ID", + "mxe": "mxe-Latn-VU", + "mxf": "mxf-Latn-CM", + "mxg": "mxg-Latn-AO", + "mxh": "mxh-Latn-CD", + "mxi": "mxi-Latn-ES", + "mxj": "mxj-Latn-IN", + "mxk": "mxk-Latn-PG", + "mxl": "mxl-Latn-BJ", + "mxm": "mxm-Latn-ZZ", + "mxn": "mxn-Latn-ID", + "mxo": "mxo-Latn-ZM", + "mxp": "mxp-Latn-MX", + "mxq": "mxq-Latn-MX", + "mxr": "mxr-Latn-MY", + "mxs": "mxs-Latn-MX", + "mxt": "mxt-Latn-MX", + "mxu": "mxu-Latn-CM", + "mxv": "mxv-Latn-MX", + "mxw": "mxw-Latn-PG", + "mxx": "mxx-Latn-CI", + "mxy": "mxy-Latn-MX", + "mxz": "mxz-Latn-ID", + "my": "my-Mymr-MM", + "myb": "myb-Latn-TD", + "myc": "myc-Latn-CD", + "mye": "mye-Latn-GA", + "myf": "myf-Latn-ET", + "myg": "myg-Latn-CM", + "myh": "myh-Latn-US", + "myj": "myj-Latn-SS", + "myk": "myk-Latn-ZZ", + "myl": "myl-Latn-ID", + "mym": "mym-Ethi-ZZ", + "myp": "myp-Latn-BR", + "myr": "myr-Latn-PE", + "myu": "myu-Latn-BR", + "myv": "myv-Cyrl-RU", + "myw": "myw-Latn-ZZ", + "myx": "myx-Latn-UG", + "myy": "myy-Latn-CO", + "myz": "myz-Mand-IR", + "mza": "mza-Latn-MX", + "mzd": "mzd-Latn-CM", + "mze": "mze-Latn-PG", + "mzh": "mzh-Latn-AR", + "mzi": "mzi-Latn-MX", + "mzj": "mzj-Latn-LR", + "mzk": "mzk-Latn-ZZ", + "mzl": "mzl-Latn-MX", + "mzm": "mzm-Latn-ZZ", + "mzn": "mzn-Arab-IR", + "mzo": "mzo-Latn-BR", + "mzp": "mzp-Latn-ZZ", + "mzq": "mzq-Latn-ID", + "mzr": "mzr-Latn-BR", + "mzt": "mzt-Latn-MY", + "mzu": "mzu-Latn-PG", + "mzv": "mzv-Latn-CF", + "mzw": "mzw-Latn-ZZ", + "mzx": "mzx-Latn-GY", + "mzz": "mzz-Latn-ZZ", + "na": "na-Latn-NR", + "naa": "naa-Latn-ID", + "nab": "nab-Latn-BR", + "nac": "nac-Latn-ZZ", + "nae": "nae-Latn-ID", + "naf": "naf-Latn-ZZ", + "nag": "nag-Latn-IN", + "naj": "naj-Latn-GN", + "nak": "nak-Latn-ZZ", + "nal": "nal-Latn-PG", + "nam": "nam-Latn-AU", + "nan": "nan-Hans-CN", + "nao": "nao-Deva-NP", + "nap": "nap-Latn-IT", + "naq": "naq-Latn-NA", + "nar": "nar-Latn-NG", + "nas": "nas-Latn-ZZ", + "nat": "nat-Latn-NG", + "naw": "naw-Latn-GH", + "nax": "nax-Latn-PG", + "nay": "nay-Latn-AU", + "naz": "naz-Latn-MX", + "nb": "nb-Latn-NO", + "nba": "nba-Latn-AO", + "nbb": "nbb-Latn-NG", + "nbc": "nbc-Latn-IN", + "nbd": "nbd-Latn-CD", + "nbe": "nbe-Latn-IN", + "nbh": "nbh-Latn-NG", + "nbi": "nbi-Latn-IN", + "nbj": "nbj-Latn-AU", + "nbk": "nbk-Latn-PG", + "nbm": "nbm-Latn-CF", + "nbn": "nbn-Latn-ID", + "nbo": "nbo-Latn-NG", + "nbp": "nbp-Latn-NG", + "nbq": "nbq-Latn-ID", + "nbr": "nbr-Latn-NG", + "nbt": "nbt-Latn-IN", + "nbt-Deva": "nbt-Deva-IN", + "nbu": "nbu-Latn-IN", + "nbv": "nbv-Latn-CM", + "nbw": "nbw-Latn-CD", + "nby": "nby-Latn-PG", + "nca": "nca-Latn-ZZ", + "ncb": "ncb-Latn-IN", + "ncb-Deva": "ncb-Deva-IN", + "ncc": "ncc-Latn-PG", + "ncd": "ncd-Deva-NP", + "nce": "nce-Latn-ZZ", + "ncf": "ncf-Latn-ZZ", + "ncg": "ncg-Latn-CA", + "nch": "nch-Latn-MX", + "nci": "nci-Latn-MX", + "ncj": "ncj-Latn-MX", + "nck": "nck-Latn-AU", + "ncl": "ncl-Latn-MX", + "ncm": "ncm-Latn-PG", + "ncn": "ncn-Latn-PG", + "nco": "nco-Latn-ZZ", + "ncq": "ncq-Laoo-LA", + "ncq-Thai": "ncq-Thai-LA", + "ncr": "ncr-Latn-CM", + "nct": "nct-Latn-IN", + "nct-Beng": "nct-Beng-IN", + "ncu": "ncu-Latn-ZZ", + "ncx": "ncx-Latn-MX", + "ncz": "ncz-Latn-US", + "nd": "nd-Latn-ZW", + "nda": "nda-Latn-CG", + "ndb": "ndb-Latn-CM", + "ndc": "ndc-Latn-MZ", + "ndd": "ndd-Latn-NG", + "ndf": "ndf-Cyrl-RU", + "ndg": "ndg-Latn-TZ", + "ndh": "ndh-Latn-TZ", + "ndi": "ndi-Latn-NG", + "ndj": "ndj-Latn-TZ", + "ndk": "ndk-Latn-CD", + "ndl": "ndl-Latn-CD", + "ndm": "ndm-Latn-TD", + "ndn": "ndn-Latn-CG", + "ndp": "ndp-Latn-UG", + "ndq": "ndq-Latn-AO", + "ndr": "ndr-Latn-NG", + "nds": "nds-Latn-DE", + "ndt": "ndt-Latn-CD", + "ndu": "ndu-Latn-CM", + "ndv": "ndv-Latn-SN", + "ndw": "ndw-Latn-CD", + "ndx": "ndx-Latn-ID", + "ndy": "ndy-Latn-CF", + "ndy-TD": "ndy-Latn-TD", + "ndz": "ndz-Latn-SS", + "ne": "ne-Deva-NP", + "nea": "nea-Latn-ID", + "neb": "neb-Latn-ZZ", + "nec": "nec-Latn-ID", + "ned": "ned-Latn-NG", + "nee": "nee-Latn-NC", + "neg": "neg-Cyrl-RU", + "neh": "neh-Tibt-BT", + "nei": "nei-Xsux-TR", + "nej": "nej-Latn-PG", + "nek": "nek-Latn-NC", + "nem": "nem-Latn-NC", + "nen": "nen-Latn-NC", + "neo": "neo-Latn-VN", + "neq": "neq-Latn-MX", + "ner": "ner-Latn-ID", + "net": "net-Latn-PG", + "neu": "neu-Latn-001", + "new": "new-Deva-NP", + "nex": "nex-Latn-ZZ", + "ney": "ney-Latn-CI", + "nez": "nez-Latn-US", + "nfa": "nfa-Latn-ID", + "nfd": "nfd-Latn-NG", + "nfl": "nfl-Latn-SB", + "nfr": "nfr-Latn-ZZ", + "nfu": "nfu-Latn-CM", + "ng": "ng-Latn-NA", + "nga": "nga-Latn-ZZ", + "ngb": "ngb-Latn-ZZ", + "ngc": "ngc-Latn-CD", + "ngd": "ngd-Latn-CF", + "nge": "nge-Latn-CM", + "ngg": "ngg-Latn-CF", + "ngh": "ngh-Latn-ZA", + "ngi": "ngi-Latn-NG", + "ngj": "ngj-Latn-CM", + "ngk": "ngk-Latn-AU", + "ngl": "ngl-Latn-MZ", + "ngm": "ngm-Latn-FM", + "ngn": "ngn-Latn-CM", + "ngp": "ngp-Latn-TZ", + "ngq": "ngq-Latn-TZ", + "ngr": "ngr-Latn-SB", + "ngs": "ngs-Latn-NG", + "ngt": "ngt-Laoo-LA", + "ngu": "ngu-Latn-MX", + "ngv": "ngv-Latn-CM", + "ngw": "ngw-Latn-NG", + "ngx": "ngx-Latn-NG", + "ngy": "ngy-Latn-CM", + "ngz": "ngz-Latn-CG", + "nha": "nha-Latn-AU", + "nhb": "nhb-Latn-ZZ", + "nhc": "nhc-Latn-MX", + "nhd": "nhd-Latn-PY", + "nhe": "nhe-Latn-MX", + "nhf": "nhf-Latn-AU", + "nhg": "nhg-Latn-MX", + "nhi": "nhi-Latn-MX", + "nhk": "nhk-Latn-MX", + "nhm": "nhm-Latn-MX", + "nhn": "nhn-Latn-MX", + "nho": "nho-Latn-PG", + "nhp": "nhp-Latn-MX", + "nhq": "nhq-Latn-MX", + "nhr": "nhr-Latn-BW", + "nht": "nht-Latn-MX", + "nhu": "nhu-Latn-CM", + "nhv": "nhv-Latn-MX", + "nhw": "nhw-Latn-MX", + "nhx": "nhx-Latn-MX", + "nhy": "nhy-Latn-MX", + "nhz": "nhz-Latn-MX", + "nia": "nia-Latn-ID", + "nib": "nib-Latn-PG", + "nid": "nid-Latn-AU", + "nie": "nie-Latn-TD", + "nif": "nif-Latn-ZZ", + "nig": "nig-Latn-AU", + "nih": "nih-Latn-TZ", + "nii": "nii-Latn-ZZ", + "nij": "nij-Latn-ID", + "nil": "nil-Latn-ID", + "nim": "nim-Latn-TZ", + "nin": "nin-Latn-ZZ", + "nio": "nio-Cyrl-RU", + "niq": "niq-Latn-KE", + "nir": "nir-Latn-ID", + "nis": "nis-Latn-PG", + "nit": "nit-Telu-IN", + "niu": "niu-Latn-NU", + "niv": "niv-Cyrl-RU", + "niv-Latn": "niv-Latn-RU", + "niw": "niw-Latn-PG", + "nix": "nix-Latn-CD", + "niy": "niy-Latn-ZZ", + "niz": "niz-Latn-ZZ", + "nja": "nja-Latn-NG", + "njb": "njb-Latn-IN", + "njd": "njd-Latn-TZ", + "njh": "njh-Latn-IN", + "nji": "nji-Latn-AU", + "njj": "njj-Latn-CM", + "njl": "njl-Latn-SS", + "njm": "njm-Latn-IN", + "njn": "njn-Latn-IN", + "njo": "njo-Latn-IN", + "njr": "njr-Latn-NG", + "njs": "njs-Latn-ID", + "njt": "njt-Latn-SR", + "nju": "nju-Latn-AU", + "njx": "njx-Latn-CG", + "njy": "njy-Latn-CM", + "njz": "njz-Latn-IN", + "njz-Beng": "njz-Beng-IN", + "nka": "nka-Latn-ZM", + "nkb": "nkb-Latn-IN", + "nkc": "nkc-Latn-CM", + "nkd": "nkd-Latn-IN", + "nke": "nke-Latn-SB", + "nkf": "nkf-Latn-IN", + "nkg": "nkg-Latn-ZZ", + "nkh": "nkh-Latn-IN", + "nki": "nki-Latn-IN", + "nki-Beng": "nki-Beng-IN", + "nkj": "nkj-Latn-ID", + "nkk": "nkk-Latn-VU", + "nkm": "nkm-Latn-PG", + "nkn": "nkn-Latn-AO", + "nko": "nko-Latn-ZZ", + "nkq": "nkq-Latn-GH", + "nkr": "nkr-Latn-FM", + "nks": "nks-Latn-ID", + "nkt": "nkt-Latn-TZ", + "nku": "nku-Latn-CI", + "nkv": "nkv-Latn-MW", + "nkw": "nkw-Latn-CD", + "nkx": "nkx-Latn-NG", + "nkz": "nkz-Latn-NG", + "nl": "nl-Latn-NL", + "nla": "nla-Latn-CM", + "nlc": "nlc-Latn-ID", + "nle": "nle-Latn-KE", + "nlg": "nlg-Latn-SB", + "nli": "nli-Arab-AF", + "nlj": "nlj-Latn-CD", + "nlk": "nlk-Latn-ID", + "nlm": "nlm-Arab-PK", + "nlo": "nlo-Latn-CD", + "nlq": "nlq-Latn-MM", + "nlu": "nlu-Latn-GH", + "nlv": "nlv-Latn-MX", + "nlw": "nlw-Latn-AU", + "nlx": "nlx-Deva-IN", + "nly": "nly-Latn-AU", + "nlz": "nlz-Latn-SB", + "nma": "nma-Latn-IN", + "nmb": "nmb-Latn-VU", + "nmc": "nmc-Latn-TD", + "nmd": "nmd-Latn-GA", + "nme": "nme-Latn-IN", + "nmf": "nmf-Latn-IN", + "nmg": "nmg-Latn-CM", + "nmh": "nmh-Latn-IN", + "nmi": "nmi-Latn-NG", + "nmj": "nmj-Latn-CF", + "nmk": "nmk-Latn-VU", + "nml": "nml-Latn-CM", + "nmm": "nmm-Deva-NP", + "nmm-Tibt": "nmm-Tibt-NP", + "nmn": "nmn-Latn-BW", + "nmo": "nmo-Latn-IN", + "nmo-Beng": "nmo-Beng-IN", + "nmp": "nmp-Latn-AU", + "nmq": "nmq-Latn-ZW", + "nmr": "nmr-Latn-CM", + "nms": "nms-Latn-VU", + "nmt": "nmt-Latn-FM", + "nmu": "nmu-Latn-US", + "nmv": "nmv-Latn-AU", + "nmw": "nmw-Latn-PG", + "nmx": "nmx-Latn-PG", + "nmz": "nmz-Latn-ZZ", + "nn": "nn-Latn-NO", + "nna": "nna-Latn-AU", + "nnb": "nnb-Latn-CD", + "nnc": "nnc-Latn-TD", + "nnd": "nnd-Latn-VU", + "nne": "nne-Latn-AO", + "nnf": "nnf-Latn-ZZ", + "nng": "nng-Latn-IN", + "nng-Beng": "nng-Beng-IN", + "nnh": "nnh-Latn-CM", + "nni": "nni-Latn-ID", + "nnj": "nnj-Latn-ET", + "nnk": "nnk-Latn-ZZ", + "nnl": "nnl-Latn-IN", + "nnm": "nnm-Latn-ZZ", + "nnn": "nnn-Latn-TD", + "nnp": "nnp-Wcho-IN", + "nnq": "nnq-Latn-TZ", + "nnr": "nnr-Latn-AU", + "nnt": "nnt-Latn-US", + "nnu": "nnu-Latn-GH", + "nnv": "nnv-Latn-AU", + "nnw": "nnw-Latn-BF", + "nny": "nny-Latn-AU", + "nnz": "nnz-Latn-CM", + "no": "no-Latn-NO", + "noa": "noa-Latn-CO", + "noc": "noc-Latn-PG", + "nod": "nod-Lana-TH", + "noe": "noe-Deva-IN", + "nof": "nof-Latn-PG", + "nog": "nog-Cyrl-RU", + "noh": "noh-Latn-PG", + "noi": "noi-Deva-IN", + "noj": "noj-Latn-CO", + "nok": "nok-Latn-US", + "nom": "nom-Latn-PE", + "non": "non-Runr-SE", + "nop": "nop-Latn-ZZ", + "noq": "noq-Latn-CD", + "nos": "nos-Yiii-CN", + "not": "not-Latn-PE", + "nou": "nou-Latn-ZZ", + "nov": "nov-Latn-001", + "now": "now-Latn-TZ", + "noy": "noy-Latn-TD", + "npb": "npb-Tibt-BT", + "npg": "npg-Latn-MM", + "nph": "nph-Latn-IN", + "npl": "npl-Latn-MX", + "npn": "npn-Latn-PG", + "npo": "npo-Latn-IN", + "nps": "nps-Latn-ID", + "npu": "npu-Latn-IN", + "npx": "npx-Latn-SB", + "npy": "npy-Latn-ID", + "nqg": "nqg-Latn-BJ", + "nqk": "nqk-Latn-BJ", + "nql": "nql-Latn-AO", + "nqm": "nqm-Latn-ID", + "nqn": "nqn-Latn-PG", + "nqo": "nqo-Nkoo-GN", + "nqq": "nqq-Latn-MM", + "nqt": "nqt-Latn-NG", + "nqy": "nqy-Latn-MM", + "nr": "nr-Latn-ZA", + "nra": "nra-Latn-GA", + "nrb": "nrb-Latn-ZZ", + "nre": "nre-Latn-IN", + "nrf": "nrf-Latn-JE", + "nrg": "nrg-Latn-VU", + "nri": "nri-Latn-IN", + "nrk": "nrk-Latn-AU", + "nrl": "nrl-Latn-AU", + "nrm": "nrm-Latn-MY", + "nrp": "nrp-Latn-IT", + "nru": "nru-Latn-CN", + "nru-Hans": "nru-Hans-CN", + "nru-Hant": "nru-Hant-CN", + "nrx": "nrx-Latn-AU", + "nrz": "nrz-Latn-PG", + "nsa": "nsa-Latn-IN", + "nsb": "nsb-Latn-ZA", + "nsc": "nsc-Latn-NG", + "nsd": "nsd-Yiii-CN", + "nse": "nse-Latn-ZM", + "nsf": "nsf-Yiii-CN", + "nsg": "nsg-Latn-TZ", + "nsh": "nsh-Latn-CM", + "nsk": "nsk-Cans-CA", + "nsm": "nsm-Latn-IN", + "nsn": "nsn-Latn-ZZ", + "nso": "nso-Latn-ZA", + "nsq": "nsq-Latn-US", + "nss": "nss-Latn-ZZ", + "nst": "nst-Tnsa-IN", + "nsu": "nsu-Latn-MX", + "nsv": "nsv-Yiii-CN", + "nsw": "nsw-Latn-VU", + "nsx": "nsx-Latn-AO", + "nsy": "nsy-Latn-ID", + "nsz": "nsz-Latn-US", + "ntd": "ntd-Latn-MY", + "nte": "nte-Latn-MZ", + "ntg": "ntg-Latn-AU", + "nti": "nti-Latn-BF", + "ntj": "ntj-Latn-AU", + "ntk": "ntk-Latn-TZ", + "ntm": "ntm-Latn-ZZ", + "nto": "nto-Latn-CD", + "ntp": "ntp-Latn-MX", + "ntr": "ntr-Latn-ZZ", + "ntu": "ntu-Latn-SB", + "ntx": "ntx-Latn-MM", + "nty": "nty-Yiii-VN", + "ntz": "ntz-Arab-IR", + "nua": "nua-Latn-NC", + "nuc": "nuc-Latn-BR", + "nud": "nud-Latn-PG", + "nue": "nue-Latn-CD", + "nuf": "nuf-Latn-CN", + "nug": "nug-Latn-AU", + "nuh": "nuh-Latn-NG", + "nui": "nui-Latn-ZZ", + "nuj": "nuj-Latn-UG", + "nuk": "nuk-Latn-CA", + "num": "num-Latn-TO", + "nun": "nun-Latn-MM", + "nuo": "nuo-Latn-VN", + "nup": "nup-Latn-ZZ", + "nuq": "nuq-Latn-PG", + "nur": "nur-Latn-PG", + "nus": "nus-Latn-SS", + "nut": "nut-Latn-VN", + "nuu": "nuu-Latn-CD", + "nuv": "nuv-Latn-ZZ", + "nuw": "nuw-Latn-FM", + "nux": "nux-Latn-ZZ", + "nuy": "nuy-Latn-AU", + "nuz": "nuz-Latn-MX", + "nv": "nv-Latn-US", + "nvh": "nvh-Latn-VU", + "nvm": "nvm-Latn-PG", + "nvo": "nvo-Latn-CM", + "nwb": "nwb-Latn-ZZ", + "nwc": "nwc-Newa-NP", + "nwc-Brah": "nwc-Brah-NP", + "nwc-Deva": "nwc-Deva-NP", + "nwc-Sidd": "nwc-Sidd-NP", + "nwe": "nwe-Latn-CM", + "nwg": "nwg-Latn-AU", + "nwi": "nwi-Latn-VU", + "nwm": "nwm-Latn-SS", + "nwo": "nwo-Latn-AU", + "nwr": "nwr-Latn-PG", + "nww": "nww-Latn-TZ", + "nwx": "nwx-Deva-NP", + "nxa": "nxa-Latn-TL", + "nxd": "nxd-Latn-CD", + "nxe": "nxe-Latn-ID", + "nxg": "nxg-Latn-ID", + "nxi": "nxi-Latn-TZ", + "nxl": "nxl-Latn-ID", + "nxn": "nxn-Latn-AU", + "nxo": "nxo-Latn-GA", + "nxq": "nxq-Latn-CN", + "nxr": "nxr-Latn-ZZ", + "nxx": "nxx-Latn-ID", + "ny": "ny-Latn-MW", + "nyb": "nyb-Latn-GH", + "nyc": "nyc-Latn-CD", + "nyd": "nyd-Latn-KE", + "nye": "nye-Latn-AO", + "nyf": "nyf-Latn-KE", + "nyg": "nyg-Latn-CD", + "nyh": "nyh-Latn-AU", + "nyi": "nyi-Latn-SD", + "nyj": "nyj-Latn-CD", + "nyk": "nyk-Latn-AO", + "nyl": "nyl-Thai-TH", + "nym": "nym-Latn-TZ", + "nyn": "nyn-Latn-UG", + "nyo": "nyo-Latn-UG", + "nyp": "nyp-Latn-UG", + "nyq": "nyq-Arab-IR", + "nyr": "nyr-Latn-MW", + "nys": "nys-Latn-AU", + "nyt": "nyt-Latn-AU", + "nyu": "nyu-Latn-MZ", + "nyv": "nyv-Latn-AU", + "nyx": "nyx-Latn-AU", + "nyy": "nyy-Latn-TZ", + "nza": "nza-Latn-CM", + "nzb": "nzb-Latn-GA", + "nzd": "nzd-Latn-CD", + "nzi": "nzi-Latn-GH", + "nzk": "nzk-Latn-CF", + "nzm": "nzm-Latn-IN", + "nzu": "nzu-Latn-CG", + "nzy": "nzy-Latn-TD", + "nzz": "nzz-Latn-ML", + "oaa": "oaa-Cyrl-RU", + "oac": "oac-Cyrl-RU", + "oar": "oar-Syrc-SY", + "oav": "oav-Geor-GE", + "obi": "obi-Latn-US", + "obk": "obk-Latn-PH", + "obl": "obl-Latn-CM", + "obm": "obm-Phnx-JO", + "obo": "obo-Latn-PH", + "obr": "obr-Mymr-MM", + "obt": "obt-Latn-FR", + "obu": "obu-Latn-NG", + "oc": "oc-Latn-FR", + "oca": "oca-Latn-PE", + "oco": "oco-Latn-GB", + "ocu": "ocu-Latn-MX", + "oda": "oda-Latn-NG", + "odk": "odk-Arab-PK", + "odt": "odt-Latn-NL", + "odu": "odu-Latn-NG", + "ofu": "ofu-Latn-NG", + "ogb": "ogb-Latn-NG", + "ogc": "ogc-Latn-ZZ", + "ogg": "ogg-Latn-NG", + "ogo": "ogo-Latn-NG", + "ogu": "ogu-Latn-NG", + "oht": "oht-Xsux-TR", + "oia": "oia-Latn-ID", + "oie": "oie-Latn-SS", + "oin": "oin-Latn-PG", + "oj": "oj-Cans-CA", + "ojb": "ojb-Latn-CA", + "ojb-Cans": "ojb-Cans-CA", + "ojc": "ojc-Latn-CA", + "ojs": "ojs-Cans-CA", + "ojv": "ojv-Latn-SB", + "ojw": "ojw-Latn-CA", + "ojw-Cans": "ojw-Cans-CA", + "oka": "oka-Latn-CA", + "okb": "okb-Latn-NG", + "okc": "okc-Latn-CD", + "okd": "okd-Latn-NG", + "oke": "oke-Latn-NG", + "okg": "okg-Latn-AU", + "oki": "oki-Latn-KE", + "okk": "okk-Latn-PG", + "okm": "okm-Hang-KR", + "oko": "oko-Hani-KR", + "okr": "okr-Latn-ZZ", + "oks": "oks-Latn-NG", + "oku": "oku-Latn-CM", + "okv": "okv-Latn-ZZ", + "okx": "okx-Latn-NG", + "okz": "okz-Khmr-KH", + "ola": "ola-Deva-NP", + "ola-Tibt": "ola-Tibt-CN", + "old": "old-Latn-TZ", + "ole": "ole-Tibt-BT", + "olk": "olk-Latn-AU", + "olm": "olm-Latn-NG", + "olo": "olo-Latn-RU", + "olr": "olr-Latn-VU", + "olt": "olt-Latn-LT", + "olu": "olu-Latn-AO", + "om": "om-Latn-ET", + "oma": "oma-Latn-US", + "omb": "omb-Latn-VU", + "omc": "omc-Latn-PE", + "omg": "omg-Latn-PE", + "omi": "omi-Latn-CD", + "omk": "omk-Cyrl-RU", + "oml": "oml-Latn-CD", + "omo": "omo-Latn-PG", + "omp": "omp-Mtei-IN", + "omr": "omr-Modi-IN", + "omt": "omt-Latn-KE", + "omu": "omu-Latn-PE", + "omw": "omw-Latn-PG", + "ona": "ona-Latn-AR", + "one": "one-Latn-CA", + "ong": "ong-Latn-ZZ", + "oni": "oni-Latn-ID", + "onj": "onj-Latn-PG", + "onk": "onk-Latn-PG", + "onn": "onn-Latn-ZZ", + "ono": "ono-Latn-CA", + "onp": "onp-Latn-IN", + "onp-Deva": "onp-Deva-IN", + "onr": "onr-Latn-PG", + "ons": "ons-Latn-ZZ", + "ont": "ont-Latn-PG", + "onu": "onu-Latn-VU", + "onx": "onx-Latn-ID", + "ood": "ood-Latn-US", + "oon": "oon-Deva-IN", + "oor": "oor-Latn-ZA", + "opa": "opa-Latn-NG", + "opk": "opk-Latn-ID", + "opm": "opm-Latn-ZZ", + "opo": "opo-Latn-PG", + "opt": "opt-Latn-MX", + "opy": "opy-Latn-BR", + "or": "or-Orya-IN", + "ora": "ora-Latn-SB", + "orc": "orc-Latn-KE", + "ore": "ore-Latn-PE", + "org": "org-Latn-NG", + "orn": "orn-Latn-MY", + "oro": "oro-Latn-ZZ", + "orr": "orr-Latn-NG", + "ors": "ors-Latn-MY", + "ort": "ort-Telu-IN", + "oru": "oru-Arab-ZZ", + "orv": "orv-Cyrl-RU", + "orw": "orw-Latn-BR", + "orx": "orx-Latn-NG", + "orz": "orz-Latn-ID", + "os": "os-Cyrl-GE", + "osa": "osa-Osge-US", + "osc": "osc-Ital-IT", + "osc-Latn": "osc-Latn-IT", + "osi": "osi-Java-ID", + "oso": "oso-Latn-NG", + "osp": "osp-Latn-ES", + "ost": "ost-Latn-CM", + "osu": "osu-Latn-PG", + "osx": "osx-Latn-DE", + "ota": "ota-Arab-ZZ", + "otb": "otb-Tibt-CN", + "otd": "otd-Latn-ID", + "ote": "ote-Latn-MX", + "oti": "oti-Latn-BR", + "otk": "otk-Orkh-MN", + "otl": "otl-Latn-MX", + "otm": "otm-Latn-MX", + "otn": "otn-Latn-MX", + "otq": "otq-Latn-MX", + "otr": "otr-Latn-SD", + "ots": "ots-Latn-MX", + "ott": "ott-Latn-MX", + "otu": "otu-Latn-BR", + "otw": "otw-Latn-CA", + "otx": "otx-Latn-MX", + "oty": "oty-Gran-IN", + "otz": "otz-Latn-MX", + "oub": "oub-Latn-LR", + "oue": "oue-Latn-PG", + "oui": "oui-Ougr-143", + "oum": "oum-Latn-PG", + "ovd": "ovd-Latn-SE", + "owi": "owi-Latn-PG", + "owl": "owl-Latn-GB", + "oyd": "oyd-Latn-ET", + "oym": "oym-Latn-BR", + "oyy": "oyy-Latn-PG", + "ozm": "ozm-Latn-ZZ", + "pa": "pa-Guru-IN", + "pa-Arab": "pa-Arab-PK", + "pa-PK": "pa-Arab-PK", + "pab": "pab-Latn-BR", + "pac": "pac-Latn-VN", + "pad": "pad-Latn-BR", + "pae": "pae-Latn-CD", + "paf": "paf-Latn-BR", + "pag": "pag-Latn-PH", + "pah": "pah-Latn-BR", + "pai": "pai-Latn-NG", + "pak": "pak-Latn-BR", + "pal": "pal-Phli-IR", + "pal-Phlp": "pal-Phlp-CN", + "pam": "pam-Latn-PH", + "pao": "pao-Latn-US", + "pap": "pap-Latn-CW", + "paq": "paq-Cyrl-TJ", + "par": "par-Latn-US", + "pas": "pas-Latn-ID", + "pau": "pau-Latn-PW", + "pav": "pav-Latn-BR", + "paw": "paw-Latn-US", + "pax": "pax-Latn-BR", + "pay": "pay-Latn-HN", + "paz": "paz-Latn-BR", + "pbb": "pbb-Latn-CO", + "pbc": "pbc-Latn-GY", + "pbe": "pbe-Latn-MX", + "pbf": "pbf-Latn-MX", + "pbg": "pbg-Latn-VE", + "pbh": "pbh-Latn-VE", + "pbi": "pbi-Latn-ZZ", + "pbl": "pbl-Latn-NG", + "pbm": "pbm-Latn-MX", + "pbn": "pbn-Latn-NG", + "pbo": "pbo-Latn-GW", + "pbp": "pbp-Latn-GN", + "pbr": "pbr-Latn-TZ", + "pbs": "pbs-Latn-MX", + "pbt": "pbt-Arab-AF", + "pbv": "pbv-Latn-IN", + "pby": "pby-Latn-PG", + "pca": "pca-Latn-MX", + "pcb": "pcb-Khmr-KH", + "pcc": "pcc-Latn-CN", + "pcc-Hani": "pcc-Hani-CN", + "pcd": "pcd-Latn-FR", + "pce": "pce-Mymr-MM", + "pce-Thai": "pce-Thai-TH", + "pcf": "pcf-Mlym-IN", + "pcg": "pcg-Mlym-IN", + "pcg-Knda": "pcg-Knda-IN", + "pcg-Taml": "pcg-Taml-IN", + "pch": "pch-Deva-IN", + "pci": "pci-Deva-IN", + "pci-Orya": "pci-Orya-IN", + "pcj": "pcj-Telu-IN", + "pck": "pck-Latn-IN", + "pcm": "pcm-Latn-NG", + "pcn": "pcn-Latn-NG", + "pcp": "pcp-Latn-BO", + "pcw": "pcw-Latn-NG", + "pda": "pda-Latn-PG", + "pdc": "pdc-Latn-US", + "pdn": "pdn-Latn-ID", + "pdo": "pdo-Latn-ID", + "pdt": "pdt-Latn-CA", + "pdu": "pdu-Latn-MM", + "pdu-Mymr": "pdu-Mymr-MM", + "pea": "pea-Latn-ID", + "peb": "peb-Latn-US", + "ped": "ped-Latn-ZZ", + "pee": "pee-Latn-ID", + "peg": "peg-Orya-IN", + "pei": "pei-Latn-MX", + "pek": "pek-Latn-PG", + "pel": "pel-Latn-ID", + "pem": "pem-Latn-CD", + "peo": "peo-Xpeo-IR", + "pep": "pep-Latn-PG", + "peq": "peq-Latn-US", + "pev": "pev-Latn-VE", + "pex": "pex-Latn-ZZ", + "pey": "pey-Latn-ID", + "pez": "pez-Latn-MY", + "pfa": "pfa-Latn-FM", + "pfe": "pfe-Latn-CM", + "pfl": "pfl-Latn-DE", + "pga": "pga-Latn-SS", + "pgd": "pgd-Khar-PK", + "pgg": "pgg-Deva-IN", + "pgi": "pgi-Latn-PG", + "pgk": "pgk-Latn-VU", + "pgl": "pgl-Ogam-IE", + "pgn": "pgn-Ital-IT", + "pgs": "pgs-Latn-NG", + "pgu": "pgu-Latn-ID", + "phd": "phd-Deva-IN", + "phg": "phg-Latn-VN", + "phh": "phh-Latn-VN", + "phk": "phk-Mymr-IN", + "phl": "phl-Arab-ZZ", + "phm": "phm-Latn-MZ", + "phn": "phn-Phnx-LB", + "pho": "pho-Laoo-LA", + "phr": "phr-Arab-PK", + "pht": "pht-Thai-TH", + "phv": "phv-Arab-AF", + "phw": "phw-Deva-NP", + "pi": "pi-Sinh-IN", + "pi-Brah": "pi-Brah-IN", + "pi-Deva": "pi-Deva-IN", + "pi-Khar": "pi-Khar-IN", + "pi-Khmr": "pi-Khmr-IN", + "pi-Mymr": "pi-Mymr-IN", + "pi-Thai": "pi-Thai-IN", + "pia": "pia-Latn-MX", + "pib": "pib-Latn-PE", + "pic": "pic-Latn-GA", + "pid": "pid-Latn-VE", + "pif": "pif-Latn-FM", + "pig": "pig-Latn-PE", + "pih": "pih-Latn-NF", + "pij": "pij-Latn-CO", + "pil": "pil-Latn-ZZ", + "pim": "pim-Latn-US", + "pin": "pin-Latn-PG", + "pio": "pio-Latn-CO", + "pip": "pip-Latn-ZZ", + "pir": "pir-Latn-BR", + "pis": "pis-Latn-SB", + "pit": "pit-Latn-AU", + "piu": "piu-Latn-AU", + "piv": "piv-Latn-SB", + "piw": "piw-Latn-TZ", + "pix": "pix-Latn-PG", + "piy": "piy-Latn-NG", + "piz": "piz-Latn-NC", + "pjt": "pjt-Latn-AU", + "pka": "pka-Brah-IN", + "pkb": "pkb-Latn-KE", + "pkg": "pkg-Latn-PG", + "pkh": "pkh-Latn-BD", + "pkh-Deva": "pkh-Deva-BD", + "pkn": "pkn-Latn-AU", + "pko": "pko-Latn-KE", + "pkp": "pkp-Latn-CK", + "pkr": "pkr-Mlym-IN", + "pku": "pku-Latn-ID", + "pl": "pl-Latn-PL", + "pla": "pla-Latn-ZZ", + "plb": "plb-Latn-VU", + "plc": "plc-Latn-PH", + "pld": "pld-Latn-GB", + "ple": "ple-Latn-ID", + "plg": "plg-Latn-AR", + "plh": "plh-Latn-ID", + "plj": "plj-Latn-NG", + "plk": "plk-Arab-PK", + "pll": "pll-Mymr-MM", + "pln": "pln-Latn-CO", + "plo": "plo-Latn-MX", + "plr": "plr-Latn-CI", + "pls": "pls-Latn-MX", + "plu": "plu-Latn-BR", + "plv": "plv-Latn-PH", + "plw": "plw-Latn-PH", + "plz": "plz-Latn-MY", + "pma": "pma-Latn-VU", + "pmb": "pmb-Latn-CD", + "pmd": "pmd-Latn-AU", + "pme": "pme-Latn-NC", + "pmf": "pmf-Latn-ID", + "pmh": "pmh-Brah-IN", + "pmi": "pmi-Latn-CN", + "pmj": "pmj-Latn-CN", + "pml": "pml-Latn-TN", + "pmm": "pmm-Latn-CM", + "pmn": "pmn-Latn-CM", + "pmo": "pmo-Latn-ID", + "pmq": "pmq-Latn-MX", + "pmr": "pmr-Latn-PG", + "pms": "pms-Latn-IT", + "pmt": "pmt-Latn-PF", + "pmw": "pmw-Latn-US", + "pmx": "pmx-Latn-IN", + "pmy": "pmy-Latn-ID", + "pmz": "pmz-Latn-MX", + "pna": "pna-Latn-MY", + "pnc": "pnc-Latn-ID", + "pnd": "pnd-Latn-AO", + "pne": "pne-Latn-MY", + "png": "png-Latn-ZZ", + "pnh": "pnh-Latn-CK", + "pni": "pni-Latn-ID", + "pnj": "pnj-Latn-AU", + "pnk": "pnk-Latn-BO", + "pnl": "pnl-Latn-BF", + "pnm": "pnm-Latn-MY", + "pnn": "pnn-Latn-ZZ", + "pno": "pno-Latn-PE", + "pnp": "pnp-Latn-ID", + "pnq": "pnq-Latn-BF", + "pnr": "pnr-Latn-PG", + "pns": "pns-Latn-ID", + "pnt": "pnt-Grek-GR", + "pnv": "pnv-Latn-AU", + "pnw": "pnw-Latn-AU", + "pny": "pny-Latn-CM", + "pnz": "pnz-Latn-CF", + "poc": "poc-Latn-GT", + "poe": "poe-Latn-MX", + "pof": "pof-Latn-CD", + "pog": "pog-Latn-BR", + "poh": "poh-Latn-GT", + "poi": "poi-Latn-MX", + "pok": "pok-Latn-BR", + "pom": "pom-Latn-US", + "pon": "pon-Latn-FM", + "poo": "poo-Latn-US", + "pop": "pop-Latn-NC", + "poq": "poq-Latn-MX", + "pos": "pos-Latn-MX", + "pot": "pot-Latn-US", + "pov": "pov-Latn-GW", + "pow": "pow-Latn-MX", + "poy": "poy-Latn-TZ", + "ppa": "bfy-Deva-IN", + "ppe": "ppe-Latn-PG", + "ppi": "ppi-Latn-MX", + "ppk": "ppk-Latn-ID", + "ppl": "ppl-Latn-SV", + "ppm": "ppm-Latn-ID", + "ppn": "ppn-Latn-PG", + "ppo": "ppo-Latn-ZZ", + "ppp": "ppp-Latn-CD", + "ppq": "ppq-Latn-PG", + "pps": "pps-Latn-MX", + "ppt": "ppt-Latn-PG", + "pqa": "pqa-Latn-NG", + "pqm": "pqm-Latn-CA", + "pra": "pra-Khar-PK", + "prc": "prc-Arab-AF", + "prd": "prd-Arab-IR", + "pre": "pre-Latn-ST", + "prf": "prf-Latn-PH", + "prg": "prg-Latn-001", + "prh": "prh-Latn-PH", + "pri": "pri-Latn-NC", + "prk": "prk-Latn-MM", + "prm": "prm-Latn-PG", + "pro": "pro-Latn-FR", + "prp": "prp-Gujr-IN", + "prq": "prq-Latn-PE", + "prr": "prr-Latn-BR", + "prt": "prt-Thai-TH", + "pru": "pru-Latn-ID", + "prw": "prw-Latn-PG", + "prx": "prx-Arab-IN", + "prx-Tibt": "prx-Tibt-IN", + "ps": "ps-Arab-AF", + "psa": "psa-Latn-ID", + "pse": "pse-Latn-ID", + "psh": "psh-Arab-AF", + "psi": "psi-Arab-AF", + "psm": "psm-Latn-BO", + "psn": "psn-Latn-ID", + "psq": "psq-Latn-PG", + "pss": "pss-Latn-ZZ", + "pst": "pst-Arab-PK", + "psw": "psw-Latn-VU", + "pt": "pt-Latn-BR", + "pta": "pta-Latn-PY", + "pth": "pth-Latn-BR", + "pti": "pti-Latn-AU", + "ptn": "ptn-Latn-ID", + "pto": "pto-Latn-BR", + "ptp": "ptp-Latn-ZZ", + "ptr": "ptr-Latn-VU", + "ptt": "ptt-Latn-ID", + "ptu": "ptu-Latn-ID", + "ptv": "ptv-Latn-VU", + "pua": "pua-Latn-MX", + "pub": "pub-Latn-IN", + "puc": "puc-Latn-ID", + "pud": "pud-Latn-ID", + "pue": "pue-Latn-AR", + "puf": "puf-Latn-ID", + "pug": "pug-Latn-BF", + "pui": "pui-Latn-CO", + "puj": "puj-Latn-ID", + "pum": "pum-Deva-NP", + "puo": "puo-Latn-VN", + "pup": "pup-Latn-PG", + "puq": "puq-Latn-PE", + "pur": "pur-Latn-BR", + "put": "put-Latn-ID", + "puu": "puu-Latn-GA", + "puw": "puw-Latn-FM", + "pux": "pux-Latn-PG", + "puy": "puy-Latn-US", + "pwa": "pwa-Latn-ZZ", + "pwb": "pwb-Latn-NG", + "pwg": "pwg-Latn-PG", + "pwm": "pwm-Latn-PH", + "pwn": "pwn-Latn-TW", + "pwo": "pwo-Mymr-MM", + "pwr": "pwr-Deva-IN", + "pww": "pww-Thai-TH", + "pxm": "pxm-Latn-MX", + "pye": "pye-Latn-CI", + "pym": "pym-Latn-NG", + "pyn": "pyn-Latn-BR", + "pyu": "pyu-Latn-TW", + "pyu-Hani": "pyu-Hani-TW", + "pyx": "pyx-Mymr-MM", + "pyy": "pyy-Latn-MM", + "pzh": "pzh-Latn-TW", + "pzn": "pzn-Latn-MM", + "qu": "qu-Latn-PE", + "qua": "qua-Latn-US", + "qub": "qub-Latn-PE", + "quc": "quc-Latn-GT", + "qud": "qud-Latn-EC", + "quf": "quf-Latn-PE", + "qug": "qug-Latn-EC", + "qui": "qui-Latn-US", + "quk": "quk-Latn-PE", + "qul": "qul-Latn-BO", + "qum": "qum-Latn-GT", + "qun": "qun-Latn-US", + "qup": "qup-Latn-PE", + "quq": "quq-Latn-ES", + "qur": "qur-Latn-PE", + "qus": "qus-Latn-AR", + "quv": "quv-Latn-GT", + "quw": "quw-Latn-EC", + "qux": "qux-Latn-PE", + "quy": "quy-Latn-PE", + "qva": "qva-Latn-PE", + "qvc": "qvc-Latn-PE", + "qve": "qve-Latn-PE", + "qvh": "qvh-Latn-PE", + "qvi": "qvi-Latn-EC", + "qvj": "qvj-Latn-EC", + "qvl": "qvl-Latn-PE", + "qvm": "qvm-Latn-PE", + "qvn": "qvn-Latn-PE", + "qvo": "qvo-Latn-PE", + "qvp": "qvp-Latn-PE", + "qvs": "qvs-Latn-PE", + "qvw": "qvw-Latn-PE", + "qvz": "qvz-Latn-EC", + "qwa": "qwa-Latn-PE", + "qwc": "qwc-Latn-PE", + "qwh": "qwh-Latn-PE", + "qwm": "qwm-Latn-RU", + "qwm-Cyrl": "qwm-Cyrl-RU", + "qwm-Runr": "qwm-Runr-RU", + "qws": "qws-Latn-PE", + "qwt": "qwt-Latn-US", + "qxa": "qxa-Latn-PE", + "qxc": "qxc-Latn-PE", + "qxh": "qxh-Latn-PE", + "qxl": "qxl-Latn-EC", + "qxn": "qxn-Latn-PE", + "qxo": "qxo-Latn-PE", + "qxp": "qxp-Latn-PE", + "qxq": "qxq-Arab-IR", + "qxr": "qxr-Latn-EC", + "qxt": "qxt-Latn-PE", + "qxu": "qxu-Latn-PE", + "qxw": "qxw-Latn-PE", + "qya": "qya-Latn-001", + "qyp": "qyp-Latn-US", + "raa": "raa-Deva-NP", + "rab": "rab-Deva-NP", + "rac": "rac-Latn-ID", + "rad": "rad-Latn-VN", + "raf": "raf-Deva-NP", + "rag": "rag-Latn-KE", + "rah": "rah-Beng-IN", + "rah-Latn": "rah-Latn-IN", + "rai": "rai-Latn-ZZ", + "raj": "raj-Deva-IN", + "rak": "rak-Latn-PG", + "ram": "ram-Latn-BR", + "ran": "ran-Latn-ID", + "rao": "rao-Latn-ZZ", + "rap": "rap-Latn-CL", + "rar": "rar-Latn-CK", + "rav": "rav-Deva-NP", + "raw": "raw-Latn-MM", + "rax": "rax-Latn-NG", + "ray": "ray-Latn-PF", + "raz": "raz-Latn-ID", + "rbb": "rbb-Mymr-MM", + "rbk": "rbk-Latn-PH", + "rbl": "rbl-Latn-PH", + "rbp": "rbp-Latn-AU", + "rcf": "rcf-Latn-RE", + "rdb": "rdb-Arab-IR", + "rea": "rea-Latn-PG", + "reb": "reb-Latn-ID", + "ree": "ree-Latn-MY", + "reg": "reg-Latn-TZ", + "rei": "rei-Orya-IN", + "rei-Telu": "rei-Telu-IN", + "rej": "rej-Latn-ID", + "rel": "rel-Latn-ZZ", + "rem": "rem-Latn-PE", + "ren": "ren-Latn-VN", + "res": "res-Latn-ZZ", + "ret": "ret-Latn-ID", + "rey": "rey-Latn-BO", + "rga": "rga-Latn-VU", + "rgn": "rgn-Latn-IT", + "rgr": "rgr-Latn-PE", + "rgs": "rgs-Latn-VN", + "rgu": "rgu-Latn-ID", + "rhg": "rhg-Rohg-MM", + "rhp": "rhp-Latn-PG", + "ria": "ria-Latn-IN", + "rif": "rif-Latn-MA", + "ril": "ril-Latn-MM", + "rim": "rim-Latn-TZ", + "rin": "rin-Latn-NG", + "rir": "rir-Latn-ID", + "rit": "rit-Latn-AU", + "riu": "riu-Latn-ID", + "rjg": "rjg-Latn-ID", + "rji": "rji-Deva-NP", + "rjs": "rjs-Deva-NP", + "rka": "rka-Khmr-KH", + "rkb": "rkb-Latn-BR", + "rkh": "rkh-Latn-CK", + "rki": "rki-Mymr-MM", + "rkm": "rkm-Latn-BF", + "rkt": "rkt-Beng-BD", + "rkw": "rkw-Latn-AU", + "rm": "rm-Latn-CH", + "rma": "rma-Latn-NI", + "rmb": "rmb-Latn-AU", + "rmc": "rmc-Latn-SK", + "rmd": "rmd-Latn-DK", + "rme": "rme-Latn-GB", + "rmf": "rmf-Latn-FI", + "rmg": "rmg-Latn-NO", + "rmh": "rmh-Latn-ID", + "rmi": "rmi-Armn-AM", + "rmk": "rmk-Latn-PG", + "rml": "rml-Latn-PL", + "rml-Cyrl": "rml-Cyrl-BY", + "rmm": "rmm-Latn-ID", + "rmn": "rmn-Latn-RS", + "rmn-Cyrl": "rmn-Cyrl-BG", + "rmn-Grek": "rmn-Grek-GR", + "rmo": "rmo-Latn-CH", + "rmp": "rmp-Latn-PG", + "rmq": "rmq-Latn-ES", + "rmt": "rmt-Arab-IR", + "rmu": "rmu-Latn-SE", + "rmw": "rmw-Latn-GB", + "rmx": "rmx-Latn-VN", + "rmz": "rmz-Mymr-IN", + "rn": "rn-Latn-BI", + "rna": "rna-Latn-ZZ", + "rnd": "rnd-Latn-CD", + "rng": "rng-Latn-MZ", + "rnl": "rnl-Latn-IN", + "rnn": "rnn-Latn-ID", + "rnr": "rnr-Latn-AU", + "rnw": "rnw-Latn-TZ", + "ro": "ro-Latn-RO", + "rob": "rob-Latn-ID", + "roc": "roc-Latn-VN", + "rod": "rod-Latn-NG", + "roe": "roe-Latn-PG", + "rof": "rof-Latn-TZ", + "rog": "rog-Latn-VN", + "rol": "rol-Latn-PH", + "rom": "rom-Latn-RO", + "rom-Cyrl": "rom-Cyrl-RO", + "roo": "roo-Latn-ZZ", + "rop": "rop-Latn-AU", + "ror": "ror-Latn-ID", + "rou": "rou-Latn-TD", + "row": "row-Latn-ID", + "rpn": "rpn-Latn-VU", + "rpt": "rpt-Latn-PG", + "rri": "rri-Latn-SB", + "rro": "rro-Latn-ZZ", + "rrt": "rrt-Latn-AU", + "rsk": "rsk-Cyrl-RS", + "rtc": "rtc-Latn-MM", + "rth": "rth-Latn-ID", + "rtm": "rtm-Latn-FJ", + "rtw": "rtw-Deva-IN", + "ru": "ru-Cyrl-RU", + "rub": "rub-Latn-UG", + "ruc": "ruc-Latn-UG", + "rue": "rue-Cyrl-UA", + "ruf": "ruf-Latn-TZ", + "rug": "rug-Latn-SB", + "rui": "rui-Latn-TZ", + "ruk": "ruk-Latn-NG", + "ruo": "ruo-Latn-HR", + "rup": "rup-Latn-RO", + "rup-Grek": "rup-Grek-GR", + "ruq": "ruq-Latn-GR", + "rut": "rut-Cyrl-RU", + "rut-Latn": "rut-Latn-AZ", + "ruu": "ruu-Latn-MY", + "ruy": "ruy-Latn-NG", + "ruz": "ruz-Latn-NG", + "rw": "rw-Latn-RW", + "rwa": "rwa-Latn-PG", + "rwk": "rwk-Latn-TZ", + "rwl": "rwl-Latn-TZ", + "rwm": "rwm-Latn-UG", + "rwo": "rwo-Latn-ZZ", + "rwr": "rwr-Deva-IN", + "rxd": "rxd-Latn-AU", + "rxw": "rxw-Latn-AU", + "ryu": "ryu-Kana-JP", + "sa": "sa-Deva-IN", + "saa": "saa-Latn-TD", + "sab": "sab-Latn-PA", + "sac": "sac-Latn-US", + "sad": "sad-Latn-TZ", + "sae": "sae-Latn-BR", + "saf": "saf-Latn-GH", + "sah": "sah-Cyrl-RU", + "saj": "saj-Latn-ID", + "sak": "sak-Latn-GA", + "sam": "sam-Samr-PS", + "sam-Hebr": "sam-Hebr-PS", + "sam-Syrc": "sam-Syrc-PS", + "sao": "sao-Latn-ID", + "saq": "saq-Latn-KE", + "sar": "sar-Latn-BO", + "sas": "sas-Latn-ID", + "sat": "sat-Olck-IN", + "sau": "sau-Latn-ID", + "sav": "sav-Latn-SN", + "saw": "saw-Latn-ID", + "sax": "sax-Latn-VU", + "say": "say-Latn-NG", + "saz": "saz-Saur-IN", + "sba": "sba-Latn-ZZ", + "sbb": "sbb-Latn-SB", + "sbc": "sbc-Latn-PG", + "sbd": "sbd-Latn-BF", + "sbe": "sbe-Latn-ZZ", + "sbg": "sbg-Latn-ID", + "sbh": "sbh-Latn-PG", + "sbi": "sbi-Latn-PG", + "sbj": "sbj-Latn-TD", + "sbk": "sbk-Latn-TZ", + "sbl": "sbl-Latn-PH", + "sbm": "sbm-Latn-TZ", + "sbn": "sbn-Arab-PK", + "sbo": "sbo-Latn-MY", + "sbp": "sbp-Latn-TZ", + "sbq": "sbq-Latn-PG", + "sbr": "sbr-Latn-ID", + "sbs": "sbs-Latn-NA", + "sbt": "sbt-Latn-ID", + "sbu": "sbu-Tibt-IN", + "sbu-Deva": "sbu-Deva-IN", + "sbv": "sbv-Latn-IT", + "sbw": "sbw-Latn-GA", + "sbx": "sbx-Latn-ID", + "sby": "sby-Latn-ZM", + "sbz": "sbz-Latn-CF", + "sc": "sc-Latn-IT", + "scb": "scb-Latn-VN", + "sce": "sce-Latn-CN", + "sce-Arab": "sce-Arab-CN", + "scf": "scf-Latn-PA", + "scg": "scg-Latn-ID", + "sch": "sch-Latn-IN", + "sci": "sci-Latn-LK", + "sck": "sck-Deva-IN", + "scl": "scl-Arab-ZZ", + "scn": "scn-Latn-IT", + "sco": "sco-Latn-GB", + "scp": "scp-Deva-NP", + "scs": "scs-Latn-CA", + "scs-Cans": "scs-Cans-CA", + "sct": "sct-Laoo-LA", + "scu": "scu-Takr-IN", + "scv": "scv-Latn-NG", + "scw": "scw-Latn-NG", + "scx": "scx-Grek-IT", + "sd": "sd-Arab-PK", + "sd-Deva": "sd-Deva-IN", + "sd-IN": "sd-Deva-IN", + "sd-Khoj": "sd-Khoj-IN", + "sd-Sind": "sd-Sind-IN", + "sda": "sda-Latn-ID", + "sdb": "sdb-Arab-IQ", + "sdc": "sdc-Latn-IT", + "sde": "sde-Latn-NG", + "sdf": "sdf-Arab-IQ", + "sdg": "sdg-Arab-AF", + "sdh": "sdh-Arab-IR", + "sdj": "sdj-Latn-CG", + "sdk": "sdk-Latn-PG", + "sdn": "sdn-Latn-IT", + "sdo": "sdo-Latn-MY", + "sdq": "sdq-Latn-ID", + "sds": "sds-Arab-TN", + "sdu": "sdu-Latn-ID", + "sdx": "sdx-Latn-MY", + "se": "se-Latn-NO", + "sea": "sea-Latn-MY", + "seb": "seb-Latn-CI", + "sec": "sec-Latn-CA", + "sed": "sed-Latn-VN", + "see": "see-Latn-US", + "sef": "sef-Latn-CI", + "seg": "seg-Latn-TZ", + "seh": "seh-Latn-MZ", + "sei": "sei-Latn-MX", + "sej": "sej-Latn-PG", + "sek": "sek-Latn-CA", + "sek-Cans": "sek-Cans-CA", + "sel": "sel-Cyrl-RU", + "sen": "sen-Latn-BF", + "seo": "seo-Latn-PG", + "sep": "sep-Latn-BF", + "seq": "seq-Latn-BF", + "ser": "ser-Latn-US", + "ses": "ses-Latn-ML", + "set": "set-Latn-ID", + "seu": "seu-Latn-ID", + "sev": "sev-Latn-CI", + "sew": "sew-Latn-PG", + "sey": "sey-Latn-EC", + "sez": "sez-Latn-MM", + "sfe": "sfe-Latn-PH", + "sfm": "sfm-Plrd-CN", + "sfw": "sfw-Latn-GH", + "sg": "sg-Latn-CF", + "sga": "sga-Ogam-IE", + "sgb": "sgb-Latn-PH", + "sgc": "sgc-Latn-KE", + "sgd": "sgd-Latn-PH", + "sge": "sge-Latn-ID", + "sgh": "sgh-Cyrl-TJ", + "sgh-Arab": "sgh-Arab-AF", + "sgh-Latn": "sgh-Latn-TJ", + "sgi": "sgi-Latn-CM", + "sgj": "sgj-Deva-IN", + "sgm": "sgm-Latn-KE", + "sgp": "sgp-Latn-IN", + "sgr": "sgr-Arab-IR", + "sgs": "sgs-Latn-LT", + "sgt": "sgt-Tibt-BT", + "sgu": "sgu-Latn-ID", + "sgw": "sgw-Ethi-ZZ", + "sgy": "sgy-Arab-AF", + "sgz": "sgz-Latn-ZZ", + "sha": "sha-Latn-NG", + "shb": "shb-Latn-BR", + "shc": "shc-Latn-CD", + "shd": "shd-Arab-PK", + "she": "she-Latn-ET", + "shg": "shg-Latn-BW", + "shh": "shh-Latn-US", + "shi": "shi-Tfng-MA", + "shj": "shj-Latn-SD", + "shk": "shk-Latn-ZZ", + "shm": "shm-Arab-IR", + "shn": "shn-Mymr-MM", + "sho": "sho-Latn-NG", + "shp": "shp-Latn-PE", + "shq": "shq-Latn-ZM", + "shr": "shr-Latn-CD", + "shs": "shs-Latn-CA", + "sht": "sht-Latn-US", + "shu": "shu-Arab-ZZ", + "shv": "shv-Arab-OM", + "shw": "shw-Latn-SD", + "shy": "shy-Latn-DZ", + "shy-Arab": "shy-Arab-DZ", + "shy-Tfng": "shy-Tfng-DZ", + "shz": "shz-Latn-ML", + "si": "si-Sinh-LK", + "sia": "sia-Cyrl-RU", + "sib": "sib-Latn-MY", + "sid": "sid-Latn-ET", + "sie": "sie-Latn-ZM", + "sif": "sif-Latn-BF", + "sig": "sig-Latn-ZZ", + "sih": "sih-Latn-NC", + "sii": "sii-Latn-IN", + "sij": "sij-Latn-PG", + "sik": "sik-Latn-BR", + "sil": "sil-Latn-ZZ", + "sim": "sim-Latn-ZZ", + "sip": "sip-Tibt-IN", + "siq": "siq-Latn-PG", + "sir": "sir-Latn-NG", + "sis": "sis-Latn-US", + "siu": "siu-Latn-PG", + "siv": "siv-Latn-PG", + "siw": "siw-Latn-PG", + "six": "six-Latn-PG", + "siy": "siy-Arab-IR", + "siz": "siz-Arab-EG", + "sja": "sja-Latn-CO", + "sjb": "sjb-Latn-ID", + "sjd": "sjd-Cyrl-RU", + "sje": "sje-Latn-SE", + "sjg": "sjg-Latn-TD", + "sjl": "sjl-Latn-IN", + "sjm": "sjm-Latn-PH", + "sjp": "sjp-Deva-IN", + "sjp-Beng": "sjp-Beng-IN", + "sjr": "sjr-Latn-ZZ", + "sjt": "sjt-Cyrl-RU", + "sju": "sju-Latn-SE", + "sjw": "sjw-Latn-US", + "sk": "sk-Latn-SK", + "ska": "ska-Latn-US", + "skb": "skb-Thai-TH", + "skc": "skc-Latn-ZZ", + "skd": "skd-Latn-US", + "ske": "ske-Latn-VU", + "skf": "skf-Latn-BR", + "skg": "skg-Latn-MG", + "skh": "skh-Latn-ID", + "ski": "ski-Latn-ID", + "skj": "skj-Deva-NP", + "skm": "skm-Latn-PG", + "skn": "skn-Latn-PH", + "sko": "sko-Latn-ID", + "skp": "skp-Latn-MY", + "skq": "skq-Latn-BF", + "skr": "skr-Arab-PK", + "sks": "sks-Latn-ZZ", + "skt": "skt-Latn-CD", + "sku": "sku-Latn-VU", + "skv": "skv-Latn-ID", + "skw": "skw-Latn-GY", + "skx": "skx-Latn-ID", + "sky": "sky-Latn-SB", + "skz": "skz-Latn-ID", + "sl": "sl-Latn-SI", + "slc": "slc-Latn-CO", + "sld": "sld-Latn-ZZ", + "slg": "slg-Latn-ID", + "slh": "slh-Latn-US", + "sli": "sli-Latn-PL", + "slj": "slj-Latn-BR", + "sll": "sll-Latn-ZZ", + "slm": "slm-Latn-PH", + "sln": "sln-Latn-US", + "slp": "slp-Latn-ID", + "slq": "slq-Arab-IR", + "slr": "slr-Latn-CN", + "slu": "slu-Latn-ID", + "slw": "slw-Latn-PG", + "slx": "slx-Latn-CD", + "sly": "sly-Latn-ID", + "slz": "slz-Latn-ID", + "sm": "sm-Latn-WS", + "sma": "sma-Latn-SE", + "smb": "smb-Latn-PG", + "smc": "smc-Latn-PG", + "smd": "kmb-Latn-AO", + "smf": "smf-Latn-PG", + "smg": "smg-Latn-PG", + "smh": "smh-Yiii-CN", + "smj": "smj-Latn-SE", + "smk": "smk-Latn-PH", + "sml": "sml-Latn-PH", + "smn": "smn-Latn-FI", + "smp": "smp-Samr-IL", + "smq": "smq-Latn-ZZ", + "smr": "smr-Latn-ID", + "sms": "sms-Latn-FI", + "smt": "smt-Latn-IN", + "smu": "smu-Khmr-KH", + "smw": "smw-Latn-ID", + "smx": "smx-Latn-CD", + "smy": "smy-Arab-IR", + "smz": "smz-Latn-PG", + "sn": "sn-Latn-ZW", + "snb": "iba-Latn-MY", + "snc": "snc-Latn-ZZ", + "sne": "sne-Latn-MY", + "snf": "snf-Latn-SN", + "sng": "sng-Latn-CD", + "sng-Brai": "sng-Brai-CD", + "sni": "sni-Latn-PE", + "snj": "snj-Latn-CF", + "snk": "snk-Latn-ML", + "snl": "snl-Latn-PH", + "snm": "snm-Latn-UG", + "snn": "snn-Latn-CO", + "sno": "sno-Latn-US", + "snp": "snp-Latn-ZZ", + "snq": "snq-Latn-GA", + "snr": "snr-Latn-PG", + "sns": "sns-Latn-VU", + "snu": "snu-Latn-ID", + "snv": "snv-Latn-MY", + "snw": "snw-Latn-GH", + "snx": "snx-Latn-ZZ", + "sny": "sny-Latn-ZZ", + "snz": "snz-Latn-PG", + "so": "so-Latn-SO", + "soa": "soa-Tavt-TH", + "soa-Thai": "soa-Thai-TH", + "sob": "sob-Latn-ID", + "soc": "soc-Latn-CD", + "sod": "sod-Latn-CD", + "soe": "soe-Latn-CD", + "sog": "sog-Sogd-UZ", + "soi": "soi-Deva-NP", + "sok": "sok-Latn-ZZ", + "sol": "sol-Latn-PG", + "soo": "soo-Latn-CD", + "sop": "sop-Latn-CD", + "soq": "soq-Latn-ZZ", + "sor": "sor-Latn-TD", + "sos": "sos-Latn-BF", + "sou": "sou-Thai-TH", + "sov": "sov-Latn-PW", + "sow": "sow-Latn-PG", + "sox": "sox-Latn-CM", + "soy": "soy-Latn-ZZ", + "soz": "soz-Latn-TZ", + "spb": "spb-Latn-ID", + "spc": "spc-Latn-VE", + "spd": "spd-Latn-ZZ", + "spe": "spe-Latn-PG", + "spg": "spg-Latn-MY", + "spi": "spi-Latn-ID", + "spk": "spk-Latn-PG", + "spl": "spl-Latn-ZZ", + "spm": "spm-Latn-PG", + "spn": "spn-Latn-PY", + "spo": "spo-Latn-US", + "spp": "spp-Latn-ML", + "spq": "spq-Latn-PE", + "spr": "spr-Latn-ID", + "sps": "sps-Latn-ZZ", + "spt": "spt-Tibt-IN", + "spv": "spv-Orya-IN", + "sq": "sq-Latn-AL", + "sqa": "sqa-Latn-NG", + "sqh": "sqh-Latn-NG", + "sqm": "sqm-Latn-CF", + "sqo": "sqo-Arab-IR", + "sqq": "sqq-Laoo-LA", + "sqt": "sqt-Arab-YE", + "sqt-Latn": "sqt-Latn-YE", + "squ": "squ-Latn-CA", + "sr": "sr-Cyrl-RS", + "sr-ME": "sr-Latn-ME", + "sr-RO": "sr-Latn-RO", + "sr-RU": "sr-Latn-RU", + "sr-TR": "sr-Latn-TR", + "sra": "sra-Latn-PG", + "srb": "srb-Sora-IN", + "sre": "sre-Latn-ID", + "srf": "srf-Latn-PG", + "srg": "srg-Latn-PH", + "srh": "srh-Arab-CN", + "sri": "sri-Latn-CO", + "srk": "srk-Latn-MY", + "srl": "srl-Latn-ID", + "srm": "srm-Latn-SR", + "srn": "srn-Latn-SR", + "sro": "sro-Latn-IT", + "srq": "srq-Latn-BO", + "srr": "srr-Latn-SN", + "srs": "srs-Latn-CA", + "srt": "srt-Latn-ID", + "sru": "sru-Latn-BR", + "srv": "srv-Latn-PH", + "srw": "srw-Latn-ID", + "srx": "srx-Deva-IN", + "sry": "sry-Latn-PG", + "srz": "srz-Arab-IR", + "ss": "ss-Latn-ZA", + "ssb": "ssb-Latn-PH", + "ssc": "ssc-Latn-TZ", + "ssd": "ssd-Latn-ZZ", + "sse": "sse-Latn-PH", + "sse-Arab": "sse-Arab-PH", + "ssf": "ssf-Latn-TW", + "ssg": "ssg-Latn-ZZ", + "ssh": "ssh-Arab-AE", + "ssj": "ssj-Latn-PG", + "ssl": "ssl-Latn-GH", + "ssm": "ssm-Latn-MY", + "ssn": "ssn-Latn-KE", + "sso": "sso-Latn-PG", + "ssq": "ssq-Latn-ID", + "sss": "sss-Laoo-LA", + "sss-Thai": "sss-Thai-TH", + "sst": "sst-Latn-PG", + "ssu": "ssu-Latn-PG", + "ssv": "ssv-Latn-VU", + "ssx": "ssx-Latn-PG", + "ssy": "ssy-Latn-ER", + "ssz": "ssz-Latn-PG", + "st": "st-Latn-ZA", + "sta": "sta-Latn-ZM", + "stb": "stb-Latn-PH", + "ste": "ste-Latn-ID", + "stf": "stf-Latn-PG", + "stg": "stg-Latn-VN", + "sth": "sth-Latn-IE", + "sti": "sti-Latn-VN", + "sti-KH": "sti-Latn-KH", + "stj": "stj-Latn-BF", + "stk": "stk-Latn-ZZ", + "stl": "stl-Latn-NL", + "stm": "stm-Latn-PG", + "stn": "stn-Latn-SB", + "sto": "sto-Latn-CA", + "stp": "stp-Latn-MX", + "stq": "stq-Latn-DE", + "str": "str-Latn-CA", + "sts": "sts-Arab-AF", + "stt": "stt-Latn-VN", + "stv": "stv-Ethi-ET", + "stv-Arab": "stv-Arab-ET", + "stw": "stw-Latn-FM", + "sty": "sty-Cyrl-RU", + "su": "su-Latn-ID", + "sua": "sua-Latn-ZZ", + "sub": "sub-Latn-CD", + "suc": "suc-Latn-PH", + "sue": "sue-Latn-ZZ", + "sug": "sug-Latn-PG", + "sui": "sui-Latn-PG", + "suj": "suj-Latn-TZ", + "suk": "suk-Latn-TZ", + "suo": "suo-Latn-PG", + "suq": "suq-Latn-ET", + "suq-Ethi": "suq-Ethi-ET", + "sur": "sur-Latn-ZZ", + "sus": "sus-Latn-GN", + "sut": "sut-Latn-NI", + "suv": "suv-Latn-IN", + "suv-Beng": "suv-Beng-IN", + "suv-Deva": "suv-Deva-IN", + "suw": "suw-Latn-TZ", + "suy": "suy-Latn-BR", + "suz": "suz-Deva-NP", + "sv": "sv-Latn-SE", + "sva": "sva-Geor-GE", + "sva-Cyrl": "sva-Cyrl-GE", + "sva-Latn": "sva-Latn-GE", + "svb": "svb-Latn-PG", + "svc": "svc-Latn-VC", + "sve": "sve-Latn-ID", + "svm": "svm-Latn-IT", + "svs": "svs-Latn-SB", + "sw": "sw-Latn-TZ", + "swb": "swb-Arab-YT", + "swc": "sw-Latn-CD", + "swf": "swf-Latn-CD", + "swg": "swg-Latn-DE", + "swi": "swi-Hani-CN", + "swj": "swj-Latn-GA", + "swk": "swk-Latn-MW", + "swm": "swm-Latn-PG", + "swo": "swo-Latn-BR", + "swp": "swp-Latn-ZZ", + "swq": "swq-Latn-CM", + "swr": "swr-Latn-ID", + "sws": "sws-Latn-ID", + "swt": "swt-Latn-ID", + "swu": "swu-Latn-ID", + "swv": "swv-Deva-IN", + "sww": "sww-Latn-VU", + "swx": "swx-Latn-BR", + "swy": "swy-Latn-TD", + "sxb": "sxb-Latn-KE", + "sxe": "sxe-Latn-GA", + "sxn": "sxn-Latn-ID", + "sxr": "sxr-Latn-TW", + "sxs": "sxs-Latn-NG", + "sxu": "sxu-Latn-DE", + "sxu-Runr": "sxu-Runr-DE", + "sxw": "sxw-Latn-ZZ", + "sya": "sya-Latn-ID", + "syb": "syb-Latn-PH", + "syc": "syc-Syrc-TR", + "syi": "syi-Latn-GA", + "syk": "syk-Latn-NG", + "syl": "syl-Beng-BD", + "sym": "sym-Latn-BF", + "syn": "syn-Syrc-IR", + "syo": "syo-Latn-KH", + "syr": "syr-Syrc-IQ", + "sys": "sys-Latn-TD", + "syw": "syw-Deva-NP", + "syx": "syx-Latn-GA", + "sza": "sza-Latn-MY", + "szb": "szb-Latn-ID", + "szc": "szc-Latn-MY", + "szd": "szd-Latn-MY", + "szg": "szg-Latn-CD", + "szl": "szl-Latn-PL", + "szn": "szn-Latn-ID", + "szp": "szp-Latn-ID", + "szv": "szv-Latn-CM", + "szw": "szw-Latn-ID", + "szy": "szy-Latn-TW", + "ta": "ta-Taml-IN", + "taa": "taa-Latn-US", + "tab": "tab-Cyrl-RU", + "tac": "tac-Latn-MX", + "tad": "tad-Latn-ID", + "tae": "tae-Latn-BR", + "taf": "taf-Latn-BR", + "tag": "tag-Latn-SD", + "taj": "taj-Deva-NP", + "tak": "tak-Latn-NG", + "tal": "tal-Latn-ZZ", + "tan": "tan-Latn-ZZ", + "tao": "tao-Latn-TW", + "tap": "tap-Latn-CD", + "taq": "taq-Latn-ZZ", + "tar": "tar-Latn-MX", + "tas": "tas-Latn-VN", + "tau": "tau-Latn-US", + "tav": "tav-Latn-CO", + "taw": "taw-Latn-PG", + "tax": "tax-Latn-TD", + "tay": "tay-Latn-TW", + "tay-Hans": "tay-Hans-TW", + "tay-Hant": "tay-Hant-TW", + "taz": "taz-Latn-SD", + "tba": "tba-Latn-BR", + "tbc": "tbc-Latn-ZZ", + "tbd": "tbd-Latn-ZZ", + "tbe": "tbe-Latn-SB", + "tbf": "tbf-Latn-ZZ", + "tbg": "tbg-Latn-ZZ", + "tbh": "tbh-Latn-AU", + "tbi": "tbi-Latn-SD", + "tbj": "tbj-Latn-PG", + "tbk": "tbk-Tagb-PH", + "tbk-Hano": "tbk-Hano-PH", + "tbk-Latn": "tbk-Latn-PH", + "tbl": "tbl-Latn-PH", + "tbm": "tbm-Latn-CD", + "tbn": "tbn-Latn-CO", + "tbo": "tbo-Latn-ZZ", + "tbp": "tbp-Latn-ID", + "tbs": "tbs-Latn-PG", + "tbt": "tbt-Latn-CD", + "tbu": "tbu-Latn-MX", + "tbv": "tbv-Latn-PG", + "tbw": "tbw-Latn-PH", + "tbx": "tbx-Latn-PG", + "tby": "tby-Latn-ID", + "tbz": "tbz-Latn-ZZ", + "tca": "tca-Latn-BR", + "tcb": "tcb-Latn-US", + "tcc": "tcc-Latn-TZ", + "tcd": "tcd-Latn-GH", + "tce": "tce-Latn-CA", + "tcf": "tcf-Latn-MX", + "tcg": "tcg-Latn-ID", + "tch": "tch-Latn-TC", + "tci": "tci-Latn-ZZ", + "tck": "tck-Latn-GA", + "tcm": "tcm-Latn-ID", + "tcn": "tcn-Tibt-NP", + "tco": "tco-Mymr-MM", + "tcp": "tcp-Latn-MM", + "tcq": "tcq-Latn-ID", + "tcs": "tcs-Latn-AU", + "tcu": "tcu-Latn-MX", + "tcw": "tcw-Latn-MX", + "tcx": "tcx-Taml-IN", + "tcy": "tcy-Knda-IN", + "tcz": "tcz-Latn-IN", + "tda": "tda-Tfng-NE", + "tda-Arab": "tda-Arab-NE", + "tda-Latn": "tda-Latn-NE", + "tdb": "tdb-Deva-IN", + "tdb-Beng": "tdb-Beng-IN", + "tdb-Kthi": "tdb-Kthi-IN", + "tdc": "tdc-Latn-CO", + "tdd": "tdd-Tale-CN", + "tde": "tde-Latn-ML", + "tdg": "tdg-Deva-NP", + "tdh": "tdh-Deva-NP", + "tdi": "tdi-Latn-ID", + "tdj": "tdj-Latn-ID", + "tdk": "tdk-Latn-NG", + "tdl": "tdl-Latn-NG", + "tdm": "tdm-Latn-GY", + "tdn": "tdn-Latn-ID", + "tdo": "tdo-Latn-NG", + "tdq": "tdq-Latn-NG", + "tdr": "tdr-Latn-VN", + "tds": "tds-Latn-ID", + "tdt": "tdt-Latn-TL", + "tdu": "dtp-Latn-MY", + "tdv": "tdv-Latn-NG", + "tdx": "tdx-Latn-MG", + "tdy": "tdy-Latn-PH", + "te": "te-Telu-IN", + "tea": "tea-Latn-MY", + "teb": "teb-Latn-EC", + "tec": "tec-Latn-KE", + "ted": "ted-Latn-ZZ", + "tee": "tee-Latn-MX", + "teg": "teg-Latn-GA", + "teh": "teh-Latn-AR", + "tei": "tei-Latn-PG", + "tek": "tek-Latn-CD", + "tem": "tem-Latn-SL", + "ten": "ten-Latn-CO", + "teo": "teo-Latn-UG", + "tep": "tep-Latn-MX", + "teq": "teq-Latn-SD", + "ter": "ter-Latn-BR", + "tes": "tes-Java-ID", + "tet": "tet-Latn-TL", + "teu": "teu-Latn-UG", + "tev": "tev-Latn-ID", + "tew": "tew-Latn-US", + "tex": "tex-Latn-SS", + "tey": "tey-Latn-SD", + "tfi": "tfi-Latn-ZZ", + "tfn": "tfn-Latn-US", + "tfo": "tfo-Latn-ID", + "tfr": "tfr-Latn-PA", + "tft": "tft-Latn-ID", + "tg": "tg-Cyrl-TJ", + "tg-Arab": "tg-Arab-PK", + "tg-PK": "tg-Arab-PK", + "tga": "tga-Latn-KE", + "tgb": "tgb-Latn-MY", + "tgc": "tgc-Latn-ZZ", + "tgd": "tgd-Latn-NG", + "tge": "tge-Deva-NP", + "tgf": "tgf-Tibt-BT", + "tgh": "tgh-Latn-TT", + "tgi": "tgi-Latn-PG", + "tgj": "tgj-Latn-IN", + "tgn": "tgn-Latn-PH", + "tgo": "tgo-Latn-ZZ", + "tgp": "tgp-Latn-VU", + "tgq": "tgq-Latn-MY", + "tgs": "tgs-Latn-VU", + "tgt": "tgt-Latn-PH", + "tgt-Hano": "tgt-Hano-PH", + "tgt-Tagb": "tgt-Tagb-PH", + "tgu": "tgu-Latn-ZZ", + "tgv": "tgv-Latn-BR", + "tgw": "tgw-Latn-CI", + "tgx": "tgx-Latn-CA", + "tgy": "tgy-Latn-SS", + "tgz": "tgz-Latn-AU", + "th": "th-Thai-TH", + "thd": "thd-Latn-AU", + "the": "the-Deva-NP", + "thf": "thf-Deva-NP", + "thh": "thh-Latn-MX", + "thi": "thi-Tale-LA", + "thk": "thk-Latn-KE", + "thl": "thl-Deva-NP", + "thm": "thm-Thai-TH", + "thp": "thp-Latn-CA", + "thp-Dupl": "thp-Dupl-CA", + "thq": "thq-Deva-NP", + "thr": "thr-Deva-NP", + "ths": "ths-Deva-NP", + "tht": "tht-Latn-CA", + "thu": "thu-Latn-SS", + "thv": "thv-Latn-DZ", + "thv-Arab": "thv-Arab-DZ", + "thv-Tfng": "thv-Tfng-DZ", + "thy": "thy-Latn-NG", + "thz": "thz-Latn-NE", + "thz-Tfng": "thz-Tfng-NE", + "ti": "ti-Ethi-ET", + "tic": "tic-Latn-SD", + "tif": "tif-Latn-ZZ", + "tig": "tig-Ethi-ER", + "tih": "tih-Latn-MY", + "tii": "tii-Latn-CD", + "tij": "tij-Deva-NP", + "tik": "tik-Latn-ZZ", + "til": "til-Latn-US", + "tim": "tim-Latn-ZZ", + "tin": "tin-Cyrl-RU", + "tio": "tio-Latn-ZZ", + "tip": "tip-Latn-ID", + "tiq": "tiq-Latn-BF", + "tis": "tis-Latn-PH", + "tit": "tit-Latn-CO", + "tiu": "tiu-Latn-PH", + "tiv": "tiv-Latn-NG", + "tiw": "tiw-Latn-AU", + "tix": "tix-Latn-US", + "tiy": "tiy-Latn-PH", + "tja": "tja-Latn-LR", + "tjg": "tjg-Latn-ID", + "tji": "tji-Latn-CN", + "tjj": "tjj-Latn-AU", + "tjl": "tjl-Mymr-MM", + "tjn": "tjn-Latn-CI", + "tjo": "tjo-Arab-DZ", + "tjp": "tjp-Latn-AU", + "tjs": "tjs-Latn-CN", + "tju": "tju-Latn-AU", + "tjw": "tjw-Latn-AU", + "tk": "tk-Latn-TM", + "tka": "tka-Latn-BR", + "tkb": "tkb-Deva-IN", + "tkd": "tkd-Latn-TL", + "tke": "tke-Latn-MZ", + "tkf": "tkf-Latn-BR", + "tkg": "tkg-Latn-MG", + "tkl": "tkl-Latn-TK", + "tkp": "tkp-Latn-SB", + "tkq": "tkq-Latn-NG", + "tkr": "tkr-Latn-AZ", + "tks": "tks-Arab-IR", + "tkt": "tkt-Deva-NP", + "tku": "tku-Latn-MX", + "tkv": "tkv-Latn-PG", + "tkw": "tkw-Latn-SB", + "tkx": "tkx-Latn-ID", + "tkz": "tkz-Latn-VN", + "tl": "fil-Latn-PH", + "tla": "tla-Latn-MX", + "tlb": "tlb-Latn-ID", + "tlc": "tlc-Latn-MX", + "tld": "tld-Latn-ID", + "tlf": "tlf-Latn-ZZ", + "tlg": "tlg-Latn-ID", + "tli": "tli-Latn-US", + "tli-Cyrl": "tli-Cyrl-US", + "tlj": "tlj-Latn-UG", + "tlk": "tlk-Latn-ID", + "tll": "tll-Latn-CD", + "tlm": "tlm-Latn-VU", + "tln": "tln-Latn-ID", + "tlp": "tlp-Latn-MX", + "tlq": "tlq-Latn-MM", + "tlr": "tlr-Latn-SB", + "tls": "tls-Latn-VU", + "tlt": "tlt-Latn-ID", + "tlu": "tlu-Latn-ID", + "tlv": "tlv-Latn-ID", + "tlx": "tlx-Latn-ZZ", + "tly": "tly-Latn-AZ", + "tma": "tma-Latn-TD", + "tmb": "tmb-Latn-VU", + "tmc": "tmc-Latn-TD", + "tmd": "tmd-Latn-PG", + "tme": "tme-Latn-BR", + "tmf": "tmf-Latn-PY", + "tmg": "tmg-Latn-ID", + "tmh": "tmh-Latn-NE", + "tmi": "tmi-Latn-VU", + "tmj": "tmj-Latn-ID", + "tmk": "tmk-Deva-NP", + "tml": "tml-Latn-ID", + "tmm": "tmm-Latn-VN", + "tmn": "tmn-Latn-ID", + "tmo": "tmo-Latn-MY", + "tmq": "tmq-Latn-PG", + "tmr": "tmr-Syrc-IL", + "tmt": "tmt-Latn-VU", + "tmu": "tmu-Latn-ID", + "tmv": "tmv-Latn-CD", + "tmw": "tmw-Latn-MY", + "tmy": "tmy-Latn-ZZ", + "tmz": "tmz-Latn-VE", + "tn": "tn-Latn-ZA", + "tna": "tna-Latn-BO", + "tnb": "tnb-Latn-CO", + "tnc": "tnc-Latn-CO", + "tnd": "tnd-Latn-CO", + "tng": "tng-Latn-TD", + "tnh": "tnh-Latn-ZZ", + "tni": "tni-Latn-ID", + "tnk": "tnk-Latn-VU", + "tnl": "tnl-Latn-VU", + "tnm": "tnm-Latn-ID", + "tnn": "tnn-Latn-VU", + "tno": "tno-Latn-BO", + "tnp": "tnp-Latn-VU", + "tnq": "tnq-Latn-PR", + "tnr": "tnr-Latn-SN", + "tns": "tns-Latn-PG", + "tnt": "tnt-Latn-ID", + "tnv": "tnv-Cakm-BD", + "tnw": "tnw-Latn-ID", + "tnx": "tnx-Latn-SB", + "tny": "tny-Latn-TZ", + "to": "to-Latn-TO", + "tob": "tob-Latn-AR", + "toc": "toc-Latn-MX", + "tod": "tod-Latn-GN", + "tof": "tof-Latn-ZZ", + "tog": "tog-Latn-MW", + "toh": "toh-Latn-MZ", + "toi": "toi-Latn-ZM", + "toj": "toj-Latn-MX", + "tok": "tok-Latn-001", + "tol": "tol-Latn-US", + "tom": "tom-Latn-ID", + "too": "too-Latn-MX", + "top": "top-Latn-MX", + "toq": "toq-Latn-ZZ", + "tor": "tor-Latn-CD", + "tos": "tos-Latn-MX", + "tou": "tou-Latn-VN", + "tov": "tov-Arab-IR", + "tow": "tow-Latn-US", + "tox": "tox-Latn-PW", + "toy": "toy-Latn-ID", + "toz": "toz-Latn-CM", + "tpa": "tpa-Latn-PG", + "tpc": "tpc-Latn-MX", + "tpe": "tpe-Latn-BD", + "tpe-Beng": "tpe-Beng-BD", + "tpf": "tpf-Latn-ID", + "tpg": "tpg-Latn-ID", + "tpi": "tpi-Latn-PG", + "tpj": "tpj-Latn-PY", + "tpk": "tpk-Latn-BR", + "tpl": "tpl-Latn-MX", + "tpm": "tpm-Latn-ZZ", + "tpn": "tpn-Latn-BR", + "tpp": "tpp-Latn-MX", + "tpr": "tpr-Latn-BR", + "tpt": "tpt-Latn-MX", + "tpu": "tpu-Khmr-KH", + "tpv": "tpv-Latn-MP", + "tpx": "tpx-Latn-MX", + "tpy": "tpy-Latn-BR", + "tpz": "tpz-Latn-ZZ", + "tqb": "tqb-Latn-BR", + "tql": "tql-Latn-VU", + "tqm": "tqm-Latn-PG", + "tqn": "tqn-Latn-US", + "tqo": "tqo-Latn-ZZ", + "tqp": "tqp-Latn-PG", + "tqt": "tqt-Latn-MX", + "tqu": "tqu-Latn-SB", + "tqw": "tqw-Latn-US", + "tr": "tr-Latn-TR", + "tra": "tra-Arab-AF", + "trb": "trb-Latn-PG", + "trc": "trc-Latn-MX", + "tre": "tre-Latn-ID", + "trf": "trf-Latn-TT", + "trg": "trg-Hebr-IL", + "trh": "trh-Latn-PG", + "tri": "tri-Latn-SR", + "trj": "trj-Latn-TD", + "trl": "trl-Latn-GB", + "trm": "trm-Arab-AF", + "trn": "trn-Latn-BO", + "tro": "tro-Latn-IN", + "trp": "trp-Latn-IN", + "trp-Beng": "trp-Beng-IN", + "trq": "trq-Latn-MX", + "trr": "trr-Latn-PE", + "trs": "trs-Latn-MX", + "trt": "trt-Latn-ID", + "tru": "tru-Latn-TR", + "trv": "trv-Latn-TW", + "trw": "trw-Arab-PK", + "trx": "trx-Latn-MY", + "try": "try-Latn-IN", + "trz": "trz-Latn-BR", + "ts": "ts-Latn-ZA", + "tsa": "tsa-Latn-CG", + "tsb": "tsb-Latn-ET", + "tsc": "tsc-Latn-MZ", + "tsd": "tsd-Grek-GR", + "tsf": "taj-Deva-NP", + "tsg": "tsg-Latn-PH", + "tsh": "tsh-Latn-CM", + "tsi": "tsi-Latn-CA", + "tsj": "tsj-Tibt-BT", + "tsl": "tsl-Latn-VN", + "tsp": "tsp-Latn-BF", + "tsr": "tsr-Latn-VU", + "tst": "tst-Latn-ML", + "tsu": "tsu-Latn-TW", + "tsv": "tsv-Latn-GA", + "tsw": "tsw-Latn-ZZ", + "tsx": "tsx-Latn-PG", + "tsz": "tsz-Latn-MX", + "tt": "tt-Cyrl-RU", + "ttb": "ttb-Latn-NG", + "ttc": "ttc-Latn-GT", + "ttd": "ttd-Latn-ZZ", + "tte": "tte-Latn-ZZ", + "ttf": "ttf-Latn-CM", + "tth": "tth-Laoo-LA", + "tti": "tti-Latn-ID", + "ttj": "ttj-Latn-UG", + "ttk": "ttk-Latn-CO", + "ttl": "ttl-Latn-ZM", + "ttm": "ttm-Latn-CA", + "ttn": "ttn-Latn-ID", + "tto": "tto-Laoo-LA", + "ttp": "ttp-Latn-ID", + "ttr": "ttr-Latn-ZZ", + "tts": "tts-Thai-TH", + "ttt": "ttt-Latn-AZ", + "ttu": "ttu-Latn-PG", + "ttv": "ttv-Latn-PG", + "ttw": "ttw-Latn-MY", + "tty": "tty-Latn-ID", + "tua": "tua-Latn-PG", + "tub": "tub-Latn-US", + "tuc": "tuc-Latn-PG", + "tud": "tud-Latn-BR", + "tue": "tue-Latn-CO", + "tuf": "tuf-Latn-CO", + "tug": "tug-Latn-TD", + "tuh": "tuh-Latn-ZZ", + "tui": "tui-Latn-CM", + "tuj": "tuj-Latn-ID", + "tul": "tul-Latn-ZZ", + "tum": "tum-Latn-MW", + "tun": "tun-Latn-US", + "tuo": "tuo-Latn-BR", + "tuq": "tuq-Latn-ZZ", + "tus": "tus-Latn-CA", + "tuu": "tuu-Latn-US", + "tuv": "tuv-Latn-KE", + "tux": "tux-Latn-BR", + "tuy": "tuy-Latn-KE", + "tuz": "tuz-Latn-BF", + "tva": "tva-Latn-SB", + "tvd": "tvd-Latn-ZZ", + "tve": "tve-Latn-ID", + "tvk": "tvk-Latn-VU", + "tvl": "tvl-Latn-TV", + "tvm": "tvm-Latn-ID", + "tvn": "tvn-Mymr-MM", + "tvo": "tvo-Latn-ID", + "tvs": "tvs-Latn-KE", + "tvt": "tvt-Latn-IN", + "tvu": "tvu-Latn-ZZ", + "tvw": "tvw-Latn-ID", + "tvx": "tvx-Latn-TW", + "twa": "twa-Latn-US", + "twb": "twb-Latn-PH", + "twd": "twd-Latn-NL", + "twe": "twe-Latn-ID", + "twf": "twf-Latn-US", + "twg": "twg-Latn-ID", + "twh": "twh-Latn-ZZ", + "twl": "twl-Latn-MZ", + "twm": "twm-Deva-IN", + "twn": "twn-Latn-CM", + "two": "two-Latn-BW", + "twp": "twp-Latn-PG", + "twq": "twq-Latn-NE", + "twr": "twr-Latn-MX", + "twt": "twt-Latn-BR", + "twu": "twu-Latn-ID", + "tww": "tww-Latn-PG", + "twx": "twx-Latn-MZ", + "twy": "twy-Latn-ID", + "txa": "txa-Latn-MY", + "txe": "txe-Latn-ID", + "txg": "txg-Tang-CN", + "txi": "txi-Latn-BR", + "txj": "txj-Latn-NG", + "txm": "txm-Latn-ID", + "txn": "txn-Latn-ID", + "txo": "txo-Toto-IN", + "txq": "txq-Latn-ID", + "txs": "txs-Latn-ID", + "txt": "txt-Latn-ID", + "txu": "txu-Latn-BR", + "txx": "txx-Latn-MY", + "txy": "txy-Latn-MG", + "ty": "ty-Latn-PF", + "tya": "tya-Latn-ZZ", + "tye": "tye-Latn-NG", + "tyh": "tyh-Latn-VN", + "tyi": "tyi-Latn-CG", + "tyj": "tyj-Latn-VN", + "tyl": "tyl-Latn-VN", + "tyn": "tyn-Latn-ID", + "typ": "typ-Latn-AU", + "tyr": "tyr-Tavt-VN", + "tys": "tys-Latn-VN", + "tyt": "tyt-Latn-VN", + "tyt-Tavt": "tyt-Tavt-VN", + "tyu": "tyu-Latn-BW", + "tyv": "tyv-Cyrl-RU", + "tyx": "tyx-Latn-CG", + "tyy": "tyy-Latn-NG", + "tyz": "tyz-Latn-VN", + "tzh": "tzh-Latn-MX", + "tzj": "tzj-Latn-GT", + "tzl": "tzl-Latn-001", + "tzm": "tzm-Latn-MA", + "tzn": "tzn-Latn-ID", + "tzo": "tzo-Latn-MX", + "tzx": "tzx-Latn-PG", + "uam": "uam-Latn-BR", + "uar": "uar-Latn-PG", + "uba": "uba-Latn-NG", + "ubi": "ubi-Latn-TD", + "ubl": "ubl-Latn-PH", + "ubr": "ubr-Latn-PG", + "ubu": "ubu-Latn-ZZ", + "uda": "uda-Latn-NG", + "ude": "ude-Cyrl-RU", + "udg": "udg-Mlym-IN", + "udi": "udi-Aghb-RU", + "udj": "udj-Latn-ID", + "udl": "udl-Latn-CM", + "udm": "udm-Cyrl-RU", + "udu": "udu-Latn-SD", + "ues": "ues-Latn-ID", + "ufi": "ufi-Latn-PG", + "ug": "ug-Arab-CN", + "ug-Cyrl": "ug-Cyrl-KZ", + "ug-KZ": "ug-Cyrl-KZ", + "ug-MN": "ug-Cyrl-MN", + "uga": "uga-Ugar-SY", + "ugb": "ugb-Latn-AU", + "uge": "uge-Latn-SB", + "ugh": "ugh-Cyrl-RU", + "ugo": "ugo-Thai-TH", + "uha": "uha-Latn-NG", + "uhn": "uhn-Latn-ID", + "uis": "uis-Latn-PG", + "uiv": "uiv-Latn-CM", + "uji": "uji-Latn-NG", + "uk": "uk-Cyrl-UA", + "uka": "uka-Latn-ID", + "ukg": "ukg-Latn-PG", + "ukh": "ukh-Latn-CF", + "uki": "uki-Orya-IN", + "ukk": "ukk-Latn-MM", + "ukp": "ukp-Latn-NG", + "ukq": "ukq-Latn-NG", + "uku": "uku-Latn-NG", + "ukv": "ukv-Latn-SS", + "ukw": "ukw-Latn-NG", + "uky": "uky-Latn-AU", + "ula": "ula-Latn-NG", + "ulb": "ulb-Latn-NG", + "ulc": "ulc-Cyrl-RU", + "ule": "ule-Latn-AR", + "ulf": "ulf-Latn-ID", + "uli": "uli-Latn-FM", + "ulk": "ulk-Latn-AU", + "ulm": "ulm-Latn-ID", + "uln": "uln-Latn-PG", + "ulu": "ulu-Latn-ID", + "ulw": "ulw-Latn-NI", + "uma": "uma-Latn-US", + "umb": "umb-Latn-AO", + "umd": "umd-Latn-AU", + "umg": "umg-Latn-AU", + "umi": "umi-Latn-MY", + "umm": "umm-Latn-NG", + "umn": "umn-Latn-MM", + "umo": "umo-Latn-BR", + "ump": "ump-Latn-AU", + "umr": "umr-Latn-AU", + "ums": "ums-Latn-ID", + "una": "una-Latn-PG", + "und": "en-Latn-US", + "und-002": "en-Latn-NG", + "und-003": "en-Latn-US", + "und-005": "pt-Latn-BR", + "und-009": "en-Latn-AU", + "und-011": "en-Latn-NG", + "und-013": "es-Latn-MX", + "und-014": "sw-Latn-TZ", + "und-015": "ar-Arab-EG", + "und-017": "sw-Latn-CD", + "und-018": "en-Latn-ZA", + "und-019": "en-Latn-US", + "und-021": "en-Latn-US", + "und-029": "es-Latn-CU", + "und-030": "zh-Hans-CN", + "und-034": "hi-Deva-IN", + "und-035": "id-Latn-ID", + "und-039": "it-Latn-IT", + "und-053": "en-Latn-AU", + "und-054": "en-Latn-PG", + "und-057": "en-Latn-GU", + "und-061": "sm-Latn-WS", + "und-142": "zh-Hans-CN", + "und-143": "uz-Latn-UZ", + "und-145": "ar-Arab-SA", + "und-150": "ru-Cyrl-RU", + "und-151": "ru-Cyrl-RU", + "und-154": "en-Latn-GB", + "und-155": "de-Latn-DE", + "und-202": "en-Latn-NG", + "und-419": "es-Latn-419", + "und-AD": "ca-Latn-AD", + "und-AE": "ar-Arab-AE", + "und-AF": "fa-Arab-AF", + "und-AL": "sq-Latn-AL", + "und-AM": "hy-Armn-AM", + "und-AO": "pt-Latn-AO", + "und-AQ": "und-Latn-AQ", + "und-AR": "es-Latn-AR", + "und-AS": "sm-Latn-AS", + "und-AT": "de-Latn-AT", + "und-AW": "nl-Latn-AW", + "und-AX": "sv-Latn-AX", + "und-AZ": "az-Latn-AZ", + "und-Adlm": "ff-Adlm-GN", + "und-Aghb": "udi-Aghb-RU", + "und-Ahom": "aho-Ahom-IN", + "und-Arab": "ar-Arab-EG", + "und-Arab-CC": "ms-Arab-CC", + "und-Arab-CN": "ug-Arab-CN", + "und-Arab-GB": "ur-Arab-GB", + "und-Arab-ID": "ms-Arab-ID", + "und-Arab-IN": "ur-Arab-IN", + "und-Arab-KH": "cja-Arab-KH", + "und-Arab-MM": "rhg-Arab-MM", + "und-Arab-MN": "kk-Arab-MN", + "und-Arab-MU": "ur-Arab-MU", + "und-Arab-NG": "ha-Arab-NG", + "und-Arab-PK": "ur-Arab-PK", + "und-Arab-TG": "apd-Arab-TG", + "und-Arab-TH": "mfa-Arab-TH", + "und-Arab-TJ": "fa-Arab-TJ", + "und-Arab-TR": "apc-Arab-TR", + "und-Arab-YT": "swb-Arab-YT", + "und-Armi": "arc-Armi-IR", + "und-Armn": "hy-Armn-AM", + "und-Avst": "ae-Avst-IR", + "und-BA": "bs-Latn-BA", + "und-BD": "bn-Beng-BD", + "und-BE": "nl-Latn-BE", + "und-BF": "fr-Latn-BF", + "und-BG": "bg-Cyrl-BG", + "und-BH": "ar-Arab-BH", + "und-BI": "rn-Latn-BI", + "und-BJ": "fr-Latn-BJ", + "und-BL": "fr-Latn-BL", + "und-BN": "ms-Latn-BN", + "und-BO": "es-Latn-BO", + "und-BQ": "pap-Latn-BQ", + "und-BR": "pt-Latn-BR", + "und-BT": "dz-Tibt-BT", + "und-BV": "und-Latn-BV", + "und-BY": "be-Cyrl-BY", + "und-Bali": "ban-Bali-ID", + "und-Bamu": "bax-Bamu-CM", + "und-Bass": "bsq-Bass-LR", + "und-Batk": "bbc-Batk-ID", + "und-Beng": "bn-Beng-BD", + "und-Bhks": "sa-Bhks-IN", + "und-Bopo": "zh-Bopo-TW", + "und-Brah": "pka-Brah-IN", + "und-Brai": "fr-Brai-FR", + "und-Bugi": "bug-Bugi-ID", + "und-Buhd": "bku-Buhd-PH", + "und-CD": "sw-Latn-CD", + "und-CF": "fr-Latn-CF", + "und-CG": "fr-Latn-CG", + "und-CH": "de-Latn-CH", + "und-CI": "fr-Latn-CI", + "und-CL": "es-Latn-CL", + "und-CM": "fr-Latn-CM", + "und-CN": "zh-Hans-CN", + "und-CO": "es-Latn-CO", + "und-CP": "und-Latn-CP", + "und-CR": "es-Latn-CR", + "und-CU": "es-Latn-CU", + "und-CV": "pt-Latn-CV", + "und-CW": "pap-Latn-CW", + "und-CY": "el-Grek-CY", + "und-CZ": "cs-Latn-CZ", + "und-Cakm": "ccp-Cakm-BD", + "und-Cans": "iu-Cans-CA", + "und-Cari": "xcr-Cari-TR", + "und-Cham": "cjm-Cham-VN", + "und-Cher": "chr-Cher-US", + "und-Chrs": "xco-Chrs-UZ", + "und-Copt": "cop-Copt-EG", + "und-Cpmn": "und-Cpmn-CY", + "und-Cpmn-CY": "und-Cpmn-CY", + "und-Cprt": "grc-Cprt-CY", + "und-Cyrl": "ru-Cyrl-RU", + "und-Cyrl-AL": "mk-Cyrl-AL", + "und-Cyrl-BA": "sr-Cyrl-BA", + "und-Cyrl-GE": "ab-Cyrl-GE", + "und-Cyrl-GR": "mk-Cyrl-GR", + "und-Cyrl-MD": "uk-Cyrl-MD", + "und-Cyrl-RO": "bg-Cyrl-RO", + "und-Cyrl-SK": "uk-Cyrl-SK", + "und-Cyrl-TR": "kbd-Cyrl-TR", + "und-Cyrl-XK": "sr-Cyrl-XK", + "und-DE": "de-Latn-DE", + "und-DJ": "aa-Latn-DJ", + "und-DK": "da-Latn-DK", + "und-DO": "es-Latn-DO", + "und-DZ": "ar-Arab-DZ", + "und-Deva": "hi-Deva-IN", + "und-Deva-BT": "ne-Deva-BT", + "und-Deva-FJ": "hif-Deva-FJ", + "und-Deva-MU": "bho-Deva-MU", + "und-Deva-PK": "btv-Deva-PK", + "und-Diak": "dv-Diak-MV", + "und-Dogr": "doi-Dogr-IN", + "und-Dupl": "fr-Dupl-FR", + "und-EA": "es-Latn-EA", + "und-EC": "es-Latn-EC", + "und-EE": "et-Latn-EE", + "und-EG": "ar-Arab-EG", + "und-EH": "ar-Arab-EH", + "und-ER": "ti-Ethi-ER", + "und-ES": "es-Latn-ES", + "und-ET": "am-Ethi-ET", + "und-EU": "en-Latn-IE", + "und-EZ": "de-Latn-EZ", + "und-Egyp": "egy-Egyp-EG", + "und-Elba": "sq-Elba-AL", + "und-Elym": "arc-Elym-IR", + "und-Ethi": "am-Ethi-ET", + "und-FI": "fi-Latn-FI", + "und-FO": "fo-Latn-FO", + "und-FR": "fr-Latn-FR", + "und-GA": "fr-Latn-GA", + "und-GE": "ka-Geor-GE", + "und-GF": "fr-Latn-GF", + "und-GH": "ak-Latn-GH", + "und-GL": "kl-Latn-GL", + "und-GN": "fr-Latn-GN", + "und-GP": "fr-Latn-GP", + "und-GQ": "es-Latn-GQ", + "und-GR": "el-Grek-GR", + "und-GS": "und-Latn-GS", + "und-GT": "es-Latn-GT", + "und-GW": "pt-Latn-GW", + "und-Geor": "ka-Geor-GE", + "und-Glag": "cu-Glag-BG", + "und-Gong": "wsg-Gong-IN", + "und-Gonm": "esg-Gonm-IN", + "und-Goth": "got-Goth-UA", + "und-Gran": "sa-Gran-IN", + "und-Grek": "el-Grek-GR", + "und-Grek-TR": "bgx-Grek-TR", + "und-Gujr": "gu-Gujr-IN", + "und-Guru": "pa-Guru-IN", + "und-HK": "zh-Hant-HK", + "und-HM": "und-Latn-HM", + "und-HN": "es-Latn-HN", + "und-HR": "hr-Latn-HR", + "und-HT": "ht-Latn-HT", + "und-HU": "hu-Latn-HU", + "und-Hanb": "zh-Hanb-TW", + "und-Hang": "ko-Hang-KR", + "und-Hani": "zh-Hani-CN", + "und-Hano": "hnn-Hano-PH", + "und-Hans": "zh-Hans-CN", + "und-Hant": "zh-Hant-TW", + "und-Hant-CA": "yue-Hant-CA", + "und-Hebr": "he-Hebr-IL", + "und-Hebr-SE": "yi-Hebr-SE", + "und-Hebr-UA": "yi-Hebr-UA", + "und-Hebr-US": "yi-Hebr-US", + "und-Hira": "ja-Hira-JP", + "und-Hluw": "hlu-Hluw-TR", + "und-Hmng": "hnj-Hmng-LA", + "und-Hmnp": "hnj-Hmnp-US", + "und-Hung": "hu-Hung-HU", + "und-IC": "es-Latn-IC", + "und-ID": "id-Latn-ID", + "und-IL": "he-Hebr-IL", + "und-IN": "hi-Deva-IN", + "und-IQ": "ar-Arab-IQ", + "und-IR": "fa-Arab-IR", + "und-IS": "is-Latn-IS", + "und-IT": "it-Latn-IT", + "und-Ital": "ett-Ital-IT", + "und-JO": "ar-Arab-JO", + "und-JP": "ja-Jpan-JP", + "und-Jamo": "ko-Jamo-KR", + "und-Java": "jv-Java-ID", + "und-Jpan": "ja-Jpan-JP", + "und-KE": "sw-Latn-KE", + "und-KG": "ky-Cyrl-KG", + "und-KH": "km-Khmr-KH", + "und-KM": "ar-Arab-KM", + "und-KP": "ko-Kore-KP", + "und-KR": "ko-Kore-KR", + "und-KW": "ar-Arab-KW", + "und-KZ": "ru-Cyrl-KZ", + "und-Kali": "eky-Kali-MM", + "und-Kana": "ja-Kana-JP", + "und-Kawi": "kaw-Kawi-ID", + "und-Khar": "pra-Khar-PK", + "und-Khmr": "km-Khmr-KH", + "und-Khoj": "sd-Khoj-IN", + "und-Kits": "zkt-Kits-CN", + "und-Knda": "kn-Knda-IN", + "und-Kore": "ko-Kore-KR", + "und-Kthi": "bho-Kthi-IN", + "und-LA": "lo-Laoo-LA", + "und-LB": "ar-Arab-LB", + "und-LI": "de-Latn-LI", + "und-LK": "si-Sinh-LK", + "und-LS": "st-Latn-LS", + "und-LT": "lt-Latn-LT", + "und-LU": "fr-Latn-LU", + "und-LV": "lv-Latn-LV", + "und-LY": "ar-Arab-LY", + "und-Lana": "nod-Lana-TH", + "und-Laoo": "lo-Laoo-LA", + "und-Laoo-AU": "hnj-Laoo-AU", + "und-Laoo-CN": "hnj-Laoo-CN", + "und-Laoo-FR": "hnj-Laoo-FR", + "und-Laoo-GF": "hnj-Laoo-GF", + "und-Laoo-MM": "hnj-Laoo-MM", + "und-Laoo-SR": "hnj-Laoo-SR", + "und-Laoo-TH": "hnj-Laoo-TH", + "und-Laoo-US": "hnj-Laoo-US", + "und-Laoo-VN": "hnj-Laoo-VN", + "und-Latn-AF": "tk-Latn-AF", + "und-Latn-AM": "ku-Latn-AM", + "und-Latn-CN": "za-Latn-CN", + "und-Latn-CY": "tr-Latn-CY", + "und-Latn-DZ": "fr-Latn-DZ", + "und-Latn-ET": "en-Latn-ET", + "und-Latn-GE": "ku-Latn-GE", + "und-Latn-IR": "tk-Latn-IR", + "und-Latn-KM": "fr-Latn-KM", + "und-Latn-MA": "fr-Latn-MA", + "und-Latn-MK": "sq-Latn-MK", + "und-Latn-MM": "kac-Latn-MM", + "und-Latn-MO": "pt-Latn-MO", + "und-Latn-MR": "fr-Latn-MR", + "und-Latn-RU": "krl-Latn-RU", + "und-Latn-SY": "fr-Latn-SY", + "und-Latn-TN": "fr-Latn-TN", + "und-Latn-TW": "trv-Latn-TW", + "und-Latn-UA": "pl-Latn-UA", + "und-Lepc": "lep-Lepc-IN", + "und-Limb": "lif-Limb-IN", + "und-Lina": "lab-Lina-GR", + "und-Linb": "grc-Linb-GR", + "und-Lisu": "lis-Lisu-CN", + "und-Lyci": "xlc-Lyci-TR", + "und-Lydi": "xld-Lydi-TR", + "und-MA": "ar-Arab-MA", + "und-MC": "fr-Latn-MC", + "und-MD": "ro-Latn-MD", + "und-ME": "sr-Latn-ME", + "und-MF": "fr-Latn-MF", + "und-MG": "mg-Latn-MG", + "und-MK": "mk-Cyrl-MK", + "und-ML": "bm-Latn-ML", + "und-MM": "my-Mymr-MM", + "und-MN": "mn-Cyrl-MN", + "und-MO": "zh-Hant-MO", + "und-MQ": "fr-Latn-MQ", + "und-MR": "ar-Arab-MR", + "und-MT": "mt-Latn-MT", + "und-MU": "mfe-Latn-MU", + "und-MV": "dv-Thaa-MV", + "und-MX": "es-Latn-MX", + "und-MY": "ms-Latn-MY", + "und-MZ": "pt-Latn-MZ", + "und-Mahj": "hi-Mahj-IN", + "und-Maka": "mak-Maka-ID", + "und-Mand": "myz-Mand-IR", + "und-Mani": "xmn-Mani-CN", + "und-Marc": "bo-Marc-CN", + "und-Medf": "dmf-Medf-NG", + "und-Mend": "men-Mend-SL", + "und-Merc": "xmr-Merc-SD", + "und-Mero": "xmr-Mero-SD", + "und-Mlym": "ml-Mlym-IN", + "und-Modi": "mr-Modi-IN", + "und-Mong": "mn-Mong-CN", + "und-Mroo": "mro-Mroo-BD", + "und-Mtei": "mni-Mtei-IN", + "und-Mult": "skr-Mult-PK", + "und-Mymr": "my-Mymr-MM", + "und-Mymr-IN": "kht-Mymr-IN", + "und-Mymr-TH": "mnw-Mymr-TH", + "und-NA": "af-Latn-NA", + "und-NC": "fr-Latn-NC", + "und-NE": "ha-Latn-NE", + "und-NI": "es-Latn-NI", + "und-NL": "nl-Latn-NL", + "und-NO": "nb-Latn-NO", + "und-NP": "ne-Deva-NP", + "und-Nagm": "unr-Nagm-IN", + "und-Nand": "sa-Nand-IN", + "und-Narb": "xna-Narb-SA", + "und-Nbat": "arc-Nbat-JO", + "und-Newa": "new-Newa-NP", + "und-Nkoo": "man-Nkoo-GN", + "und-Nshu": "zhx-Nshu-CN", + "und-OM": "ar-Arab-OM", + "und-Ogam": "sga-Ogam-IE", + "und-Olck": "sat-Olck-IN", + "und-Orkh": "otk-Orkh-MN", + "und-Orya": "or-Orya-IN", + "und-Osge": "osa-Osge-US", + "und-Osma": "so-Osma-SO", + "und-Ougr": "oui-Ougr-143", + "und-PA": "es-Latn-PA", + "und-PE": "es-Latn-PE", + "und-PF": "fr-Latn-PF", + "und-PG": "tpi-Latn-PG", + "und-PH": "fil-Latn-PH", + "und-PK": "ur-Arab-PK", + "und-PL": "pl-Latn-PL", + "und-PM": "fr-Latn-PM", + "und-PR": "es-Latn-PR", + "und-PS": "ar-Arab-PS", + "und-PT": "pt-Latn-PT", + "und-PW": "pau-Latn-PW", + "und-PY": "gn-Latn-PY", + "und-Palm": "arc-Palm-SY", + "und-Pauc": "ctd-Pauc-MM", + "und-Perm": "kv-Perm-RU", + "und-Phag": "lzh-Phag-CN", + "und-Phli": "pal-Phli-IR", + "und-Phlp": "pal-Phlp-CN", + "und-Phnx": "phn-Phnx-LB", + "und-Plrd": "hmd-Plrd-CN", + "und-Prti": "xpr-Prti-IR", + "und-QA": "ar-Arab-QA", + "und-QO": "en-Latn-DG", + "und-RE": "fr-Latn-RE", + "und-RO": "ro-Latn-RO", + "und-RS": "sr-Cyrl-RS", + "und-RU": "ru-Cyrl-RU", + "und-RW": "rw-Latn-RW", + "und-Rjng": "rej-Rjng-ID", + "und-Rohg": "rhg-Rohg-MM", + "und-Runr": "non-Runr-SE", + "und-SA": "ar-Arab-SA", + "und-SC": "fr-Latn-SC", + "und-SD": "ar-Arab-SD", + "und-SE": "sv-Latn-SE", + "und-SI": "sl-Latn-SI", + "und-SJ": "nb-Latn-SJ", + "und-SK": "sk-Latn-SK", + "und-SM": "it-Latn-SM", + "und-SN": "fr-Latn-SN", + "und-SO": "so-Latn-SO", + "und-SR": "nl-Latn-SR", + "und-ST": "pt-Latn-ST", + "und-SV": "es-Latn-SV", + "und-SY": "ar-Arab-SY", + "und-Samr": "smp-Samr-IL", + "und-Sarb": "xsa-Sarb-YE", + "und-Saur": "saz-Saur-IN", + "und-Sgnw": "ase-Sgnw-US", + "und-Shaw": "en-Shaw-GB", + "und-Shrd": "sa-Shrd-IN", + "und-Sidd": "sa-Sidd-IN", + "und-Sind": "sd-Sind-IN", + "und-Sinh": "si-Sinh-LK", + "und-Sogd": "sog-Sogd-UZ", + "und-Sogo": "sog-Sogo-UZ", + "und-Sora": "srb-Sora-IN", + "und-Soyo": "cmg-Soyo-MN", + "und-Sund": "su-Sund-ID", + "und-Sylo": "syl-Sylo-BD", + "und-Syrc": "syr-Syrc-IQ", + "und-TD": "fr-Latn-TD", + "und-TF": "fr-Latn-TF", + "und-TG": "fr-Latn-TG", + "und-TH": "th-Thai-TH", + "und-TJ": "tg-Cyrl-TJ", + "und-TK": "tkl-Latn-TK", + "und-TL": "pt-Latn-TL", + "und-TM": "tk-Latn-TM", + "und-TN": "ar-Arab-TN", + "und-TO": "to-Latn-TO", + "und-TR": "tr-Latn-TR", + "und-TV": "tvl-Latn-TV", + "und-TW": "zh-Hant-TW", + "und-TZ": "sw-Latn-TZ", + "und-Tagb": "tbw-Tagb-PH", + "und-Takr": "doi-Takr-IN", + "und-Tale": "tdd-Tale-CN", + "und-Talu": "khb-Talu-CN", + "und-Taml": "ta-Taml-IN", + "und-Tang": "txg-Tang-CN", + "und-Tavt": "blt-Tavt-VN", + "und-Telu": "te-Telu-IN", + "und-Tfng": "zgh-Tfng-MA", + "und-Tglg": "fil-Tglg-PH", + "und-Thaa": "dv-Thaa-MV", + "und-Thai": "th-Thai-TH", + "und-Thai-CN": "lcp-Thai-CN", + "und-Thai-KH": "kdt-Thai-KH", + "und-Thai-LA": "kdt-Thai-LA", + "und-Tibt": "bo-Tibt-CN", + "und-Tirh": "mai-Tirh-IN", + "und-Tnsa": "nst-Tnsa-IN", + "und-Toto": "txo-Toto-IN", + "und-UA": "uk-Cyrl-UA", + "und-UG": "sw-Latn-UG", + "und-UY": "es-Latn-UY", + "und-UZ": "uz-Latn-UZ", + "und-Ugar": "uga-Ugar-SY", + "und-VA": "it-Latn-VA", + "und-VE": "es-Latn-VE", + "und-VN": "vi-Latn-VN", + "und-VU": "bi-Latn-VU", + "und-Vaii": "vai-Vaii-LR", + "und-Vith": "sq-Vith-AL", + "und-WF": "fr-Latn-WF", + "und-WS": "sm-Latn-WS", + "und-Wara": "hoc-Wara-IN", + "und-Wcho": "nnp-Wcho-IN", + "und-XK": "sq-Latn-XK", + "und-Xpeo": "peo-Xpeo-IR", + "und-Xsux": "akk-Xsux-IQ", + "und-YE": "ar-Arab-YE", + "und-YT": "fr-Latn-YT", + "und-Yezi": "ku-Yezi-GE", + "und-Yiii": "ii-Yiii-CN", + "und-ZW": "sn-Latn-ZW", + "und-Zanb": "cmg-Zanb-MN", + "une": "une-Latn-NG", + "ung": "ung-Latn-AU", + "uni": "uni-Latn-PG", + "unk": "unk-Latn-BR", + "unm": "unm-Latn-US", + "unn": "unn-Latn-AU", + "unr": "unr-Beng-IN", + "unr-Deva": "unr-Deva-NP", + "unr-NP": "unr-Deva-NP", + "unu": "unu-Latn-PG", + "unx": "unx-Beng-IN", + "unz": "unz-Latn-ID", + "uok": "ema-Latn-ZZ", + "uon": "uon-Latn-TW", + "upi": "upi-Latn-PG", + "upv": "upv-Latn-VU", + "ur": "ur-Arab-PK", + "ura": "ura-Latn-PE", + "urb": "urb-Latn-BR", + "urc": "urc-Latn-AU", + "ure": "ure-Latn-BO", + "urf": "urf-Latn-AU", + "urg": "urg-Latn-PG", + "urh": "urh-Latn-NG", + "uri": "uri-Latn-ZZ", + "urk": "urk-Thai-TH", + "urm": "urm-Latn-PG", + "urn": "urn-Latn-ID", + "uro": "uro-Latn-PG", + "urp": "urp-Latn-BR", + "urr": "urr-Latn-VU", + "urt": "urt-Latn-ZZ", + "uru": "uru-Latn-BR", + "urv": "urv-Latn-PG", + "urw": "urw-Latn-ZZ", + "urx": "urx-Latn-PG", + "ury": "ury-Latn-ID", + "urz": "urz-Latn-BR", + "usa": "usa-Latn-ZZ", + "ush": "ush-Arab-PK", + "usi": "usi-Latn-BD", + "usi-Beng": "usi-Beng-BD", + "usk": "usk-Latn-CM", + "usp": "usp-Latn-GT", + "uss": "uss-Latn-NG", + "usu": "usu-Latn-PG", + "uta": "uta-Latn-NG", + "ute": "ute-Latn-US", + "uth": "uth-Latn-ZZ", + "utp": "utp-Latn-SB", + "utr": "utr-Latn-ZZ", + "utu": "utu-Latn-PG", + "uum": "uum-Grek-GE", + "uum-Cyrl": "uum-Cyrl-GE", + "uur": "uur-Latn-VU", + "uve": "uve-Latn-NC", + "uvh": "uvh-Latn-ZZ", + "uvl": "uvl-Latn-ZZ", + "uwa": "uwa-Latn-AU", + "uya": "uya-Latn-NG", + "uz": "uz-Latn-UZ", + "uz-AF": "uz-Arab-AF", + "uz-Arab": "uz-Arab-AF", + "uz-CN": "uz-Cyrl-CN", + "uzs": "uzs-Arab-AF", + "vaa": "vaa-Taml-IN", + "vae": "vae-Latn-CF", + "vaf": "vaf-Arab-IR", + "vag": "vag-Latn-ZZ", + "vah": "vah-Deva-IN", + "vai": "vai-Vaii-LR", + "vaj": "vaj-Latn-NA", + "val": "val-Latn-PG", + "vam": "vam-Latn-PG", + "van": "van-Latn-ZZ", + "vao": "vao-Latn-VU", + "vap": "vap-Latn-IN", + "var": "var-Latn-MX", + "vas": "vas-Deva-IN", + "vas-Gujr": "vas-Gujr-IN", + "vau": "vau-Latn-CD", + "vav": "vav-Deva-IN", + "vav-Gujr": "vav-Gujr-IN", + "vay": "vay-Deva-NP", + "vbb": "vbb-Latn-ID", + "vbk": "vbk-Latn-PH", + "ve": "ve-Latn-ZA", + "vec": "vec-Latn-IT", + "vem": "vem-Latn-NG", + "veo": "veo-Latn-US", + "vep": "vep-Latn-RU", + "ver": "ver-Latn-NG", + "vgr": "vgr-Arab-PK", + "vi": "vi-Latn-VN", + "vic": "vic-Latn-SX", + "vid": "vid-Latn-TZ", + "vif": "vif-Latn-CG", + "vig": "vig-Latn-BF", + "vil": "vil-Latn-AR", + "vin": "vin-Latn-TZ", + "vit": "vit-Latn-NG", + "viv": "viv-Latn-ZZ", + "vka": "vka-Latn-AU", + "vkj": "vkj-Latn-TD", + "vkk": "vkk-Latn-ID", + "vkl": "vkl-Latn-ID", + "vkm": "vkm-Latn-BR", + "vkn": "vkn-Latn-NG", + "vko": "vko-Latn-ID", + "vkp": "vkp-Latn-IN", + "vkp-Deva": "vkp-Deva-IN", + "vkt": "vkt-Latn-ID", + "vku": "vku-Latn-AU", + "vkz": "vkz-Latn-NG", + "vlp": "vlp-Latn-VU", + "vls": "vls-Latn-BE", + "vma": "vma-Latn-AU", + "vmb": "vmb-Latn-AU", + "vmc": "vmc-Latn-MX", + "vmd": "vmd-Knda-IN", + "vme": "vme-Latn-ID", + "vmf": "vmf-Latn-DE", + "vmg": "vmg-Latn-PG", + "vmh": "vmh-Arab-IR", + "vmi": "vmi-Latn-AU", + "vmj": "vmj-Latn-MX", + "vmk": "vmk-Latn-MZ", + "vml": "vml-Latn-AU", + "vmm": "vmm-Latn-MX", + "vmp": "vmp-Latn-MX", + "vmq": "vmq-Latn-MX", + "vmr": "vmr-Latn-MZ", + "vms": "vms-Latn-ID", + "vmu": "vmu-Latn-AU", + "vmw": "vmw-Latn-MZ", + "vmx": "vmx-Latn-MX", + "vmy": "vmy-Latn-MX", + "vmz": "vmz-Latn-MX", + "vnk": "vnk-Latn-SB", + "vnm": "vnm-Latn-VU", + "vnp": "vnp-Latn-VU", + "vo": "vo-Latn-001", + "vor": "vor-Latn-NG", + "vot": "vot-Latn-RU", + "vra": "vra-Latn-VU", + "vro": "vro-Latn-EE", + "vrs": "vrs-Latn-SB", + "vrt": "vrt-Latn-VU", + "vto": "vto-Latn-ID", + "vum": "vum-Latn-GA", + "vun": "vun-Latn-TZ", + "vut": "vut-Latn-ZZ", + "vwa": "vwa-Latn-CN", + "vwa-Mymr": "vwa-Mymr-CN", + "wa": "wa-Latn-BE", + "waa": "waa-Latn-US", + "wab": "wab-Latn-PG", + "wac": "wac-Latn-US", + "wad": "wad-Latn-ID", + "wae": "wae-Latn-CH", + "waf": "waf-Latn-BR", + "wag": "wag-Latn-PG", + "wah": "wah-Latn-ID", + "wai": "wai-Latn-ID", + "waj": "waj-Latn-ZZ", + "wal": "wal-Ethi-ET", + "wam": "wam-Latn-US", + "wan": "wan-Latn-ZZ", + "wap": "wap-Latn-GY", + "waq": "waq-Latn-AU", + "war": "war-Latn-PH", + "was": "was-Latn-US", + "wat": "wat-Latn-PG", + "wau": "wau-Latn-BR", + "wav": "wav-Latn-NG", + "waw": "waw-Latn-BR", + "wax": "wax-Latn-PG", + "way": "way-Latn-SR", + "waz": "waz-Latn-PG", + "wba": "wba-Latn-VE", + "wbb": "wbb-Latn-ID", + "wbe": "wbe-Latn-ID", + "wbf": "wbf-Latn-BF", + "wbh": "wbh-Latn-TZ", + "wbi": "wbi-Latn-TZ", + "wbj": "wbj-Latn-TZ", + "wbk": "wbk-Arab-AF", + "wbl": "wbl-Latn-PK", + "wbl-Arab": "wbl-Arab-AF", + "wbl-Cyrl": "wbl-Cyrl-TJ", + "wbm": "wbm-Latn-CN", + "wbp": "wbp-Latn-AU", + "wbq": "wbq-Telu-IN", + "wbr": "wbr-Deva-IN", + "wbt": "wbt-Latn-AU", + "wbv": "wbv-Latn-AU", + "wbw": "wbw-Latn-ID", + "wca": "wca-Latn-BR", + "wci": "wci-Latn-ZZ", + "wdd": "wdd-Latn-GA", + "wdg": "wdg-Latn-PG", + "wdj": "wdj-Latn-AU", + "wdk": "wdk-Latn-AU", + "wdt": "wdt-Latn-CA", + "wdu": "wdu-Latn-AU", + "wdy": "wdy-Latn-AU", + "wec": "wec-Latn-CI", + "wed": "wed-Latn-PG", + "weg": "weg-Latn-AU", + "weh": "weh-Latn-CM", + "wei": "wei-Latn-PG", + "wem": "wem-Latn-BJ", + "weo": "weo-Latn-ID", + "wep": "wep-Latn-DE", + "wer": "wer-Latn-ZZ", + "wes": "wes-Latn-CM", + "wet": "wet-Latn-ID", + "weu": "weu-Latn-MM", + "wew": "wew-Latn-ID", + "wfg": "wfg-Latn-ID", + "wga": "wga-Latn-AU", + "wgb": "wgb-Latn-PG", + "wgg": "wgg-Latn-AU", + "wgi": "wgi-Latn-ZZ", + "wgo": "wgo-Latn-ID", + "wgu": "wgu-Latn-AU", + "wgy": "wgy-Latn-AU", + "wha": "wha-Latn-ID", + "whg": "whg-Latn-ZZ", + "whk": "whk-Latn-ID", + "whu": "whu-Latn-ID", + "wib": "wib-Latn-ZZ", + "wic": "wic-Latn-US", + "wie": "wie-Latn-AU", + "wif": "wif-Latn-AU", + "wig": "wig-Latn-AU", + "wih": "wih-Latn-AU", + "wii": "wii-Latn-PG", + "wij": "wij-Latn-AU", + "wik": "wik-Latn-AU", + "wil": "wil-Latn-AU", + "wim": "wim-Latn-AU", + "win": "win-Latn-US", + "wir": "wir-Latn-BR", + "wiu": "wiu-Latn-ZZ", + "wiv": "wiv-Latn-ZZ", + "wiy": "wiy-Latn-US", + "wja": "wja-Latn-ZZ", + "wji": "wji-Latn-ZZ", + "wka": "wka-Latn-TZ", + "wkd": "wkd-Latn-ID", + "wkr": "wkr-Latn-AU", + "wkw": "wkw-Latn-AU", + "wky": "wky-Latn-AU", + "wla": "wla-Latn-PG", + "wlg": "wlg-Latn-AU", + "wlh": "wlh-Latn-TL", + "wli": "wli-Latn-ID", + "wlm": "wlm-Latn-GB", + "wlo": "wlo-Arab-ID", + "wlr": "wlr-Latn-VU", + "wls": "wls-Latn-WF", + "wlu": "wlu-Latn-AU", + "wlv": "wlv-Latn-AR", + "wlw": "wlw-Latn-ID", + "wlx": "wlx-Latn-GH", + "wma": "wma-Latn-NG", + "wmb": "wmb-Latn-AU", + "wmc": "wmc-Latn-PG", + "wmd": "wmd-Latn-BR", + "wme": "wme-Deva-NP", + "wmh": "wmh-Latn-TL", + "wmi": "wmi-Latn-AU", + "wmm": "wmm-Latn-ID", + "wmn": "wmn-Latn-NC", + "wmo": "wmo-Latn-ZZ", + "wms": "wms-Latn-ID", + "wmt": "wmt-Latn-AU", + "wmw": "wmw-Latn-MZ", + "wmw-Arab": "wmw-Arab-MZ", + "wmx": "wmx-Latn-PG", + "wnb": "wnb-Latn-PG", + "wnc": "wnc-Latn-ZZ", + "wnd": "wnd-Latn-AU", + "wne": "wne-Arab-PK", + "wng": "wng-Latn-ID", + "wni": "wni-Arab-KM", + "wnk": "wnk-Latn-ID", + "wnm": "wnm-Latn-AU", + "wnn": "wnn-Latn-AU", + "wno": "wno-Latn-ID", + "wnp": "wnp-Latn-PG", + "wnu": "wnu-Latn-ZZ", + "wnw": "wnw-Latn-US", + "wny": "wny-Latn-AU", + "wo": "wo-Latn-SN", + "woa": "woa-Latn-AU", + "wob": "wob-Latn-ZZ", + "woc": "woc-Latn-PG", + "wod": "wod-Latn-ID", + "woe": "woe-Latn-FM", + "wof": "wof-Latn-GM", + "wof-Arab": "wof-Arab-GM", + "wog": "wog-Latn-PG", + "woi": "woi-Latn-ID", + "wok": "wok-Latn-CM", + "wom": "wom-Latn-NG", + "won": "won-Latn-CD", + "woo": "woo-Latn-ID", + "wor": "wor-Latn-ID", + "wos": "wos-Latn-ZZ", + "wow": "wow-Latn-ID", + "wpc": "wpc-Latn-VE", + "wrb": "wrb-Latn-AU", + "wrg": "wrg-Latn-AU", + "wrh": "wrh-Latn-AU", + "wri": "wri-Latn-AU", + "wrk": "wrk-Latn-AU", + "wrl": "wrl-Latn-AU", + "wrm": "wrm-Latn-AU", + "wro": "wro-Latn-AU", + "wrp": "wrp-Latn-ID", + "wrr": "wrr-Latn-AU", + "wrs": "wrs-Latn-ZZ", + "wru": "wru-Latn-ID", + "wrv": "wrv-Latn-PG", + "wrw": "wrw-Latn-AU", + "wrx": "wrx-Latn-ID", + "wrz": "wrz-Latn-AU", + "wsa": "wsa-Latn-ID", + "wsg": "wsg-Gong-IN", + "wsi": "wsi-Latn-VU", + "wsk": "wsk-Latn-ZZ", + "wsr": "wsr-Latn-PG", + "wss": "wss-Latn-GH", + "wsu": "wsu-Latn-BR", + "wsv": "wsv-Arab-AF", + "wtf": "wtf-Latn-PG", + "wth": "wth-Latn-AU", + "wti": "wti-Latn-ET", + "wtk": "wtk-Latn-PG", + "wtm": "wtm-Deva-IN", + "wtw": "wtw-Latn-ID", + "wtw-Bugi": "wtw-Bugi-ID", + "wua": "wua-Latn-AU", + "wub": "wub-Latn-AU", + "wud": "wud-Latn-TG", + "wul": "wul-Latn-ID", + "wum": "wum-Latn-GA", + "wun": "wun-Latn-TZ", + "wur": "wur-Latn-AU", + "wut": "wut-Latn-PG", + "wuu": "wuu-Hans-CN", + "wuv": "wuv-Latn-ZZ", + "wux": "wux-Latn-AU", + "wuy": "wuy-Latn-ID", + "wwa": "wwa-Latn-ZZ", + "wwb": "wwb-Latn-AU", + "wwo": "wwo-Latn-VU", + "wwr": "wwr-Latn-AU", + "www": "www-Latn-CM", + "wxw": "wxw-Latn-AU", + "wyb": "wyb-Latn-AU", + "wyi": "wyi-Latn-AU", + "wym": "wym-Latn-PL", + "wyn": "wyn-Latn-US", + "wyr": "wyr-Latn-BR", + "wyy": "wyy-Latn-FJ", + "xaa": "xaa-Latn-ES", + "xab": "xab-Latn-NG", + "xai": "xai-Latn-BR", + "xaj": "xaj-Latn-BR", + "xak": "xak-Latn-VE", + "xal": "xal-Cyrl-RU", + "xam": "xam-Latn-ZA", + "xan": "xan-Ethi-ET", + "xao": "xao-Latn-VN", + "xar": "xar-Latn-PG", + "xas": "xas-Cyrl-RU", + "xat": "xat-Latn-BR", + "xau": "xau-Latn-ID", + "xav": "xav-Latn-BR", + "xaw": "xaw-Latn-US", + "xay": "xay-Latn-ID", + "xbb": "xbb-Latn-AU", + "xbd": "xbd-Latn-AU", + "xbe": "xbe-Latn-AU", + "xbg": "xbg-Latn-AU", + "xbi": "xbi-Latn-ZZ", + "xbj": "xbj-Latn-AU", + "xbm": "xbm-Latn-FR", + "xbn": "xbn-Latn-MY", + "xbp": "xbp-Latn-AU", + "xbr": "xbr-Latn-ID", + "xbw": "xbw-Latn-BR", + "xby": "xby-Latn-AU", + "xch": "xch-Latn-US", + "xco": "xco-Chrs-UZ", + "xcr": "xcr-Cari-TR", + "xda": "xda-Latn-AU", + "xdk": "xdk-Latn-AU", + "xdo": "xdo-Latn-AO", + "xdq": "xdq-Cyrl-RU", + "xdy": "xdy-Latn-ID", + "xed": "xed-Latn-CM", + "xeg": "xeg-Latn-ZA", + "xem": "xem-Latn-ID", + "xer": "xer-Latn-BR", + "xes": "xes-Latn-ZZ", + "xet": "xet-Latn-BR", + "xeu": "xeu-Latn-PG", + "xgb": "xgb-Latn-CI", + "xgd": "xgd-Latn-AU", + "xgg": "xgg-Latn-AU", + "xgi": "xgi-Latn-AU", + "xgm": "xgm-Latn-AU", + "xgu": "xgu-Latn-AU", + "xgw": "xgw-Latn-AU", + "xh": "xh-Latn-ZA", + "xhe": "xhe-Arab-PK", + "xhm": "xhm-Khmr-KH", + "xhv": "xhv-Latn-VN", + "xii": "xii-Latn-ZA", + "xin": "xin-Latn-GT", + "xir": "xir-Latn-BR", + "xis": "xis-Orya-IN", + "xiy": "xiy-Latn-BR", + "xjb": "xjb-Latn-AU", + "xjt": "xjt-Latn-AU", + "xka": "xka-Arab-PK", + "xkb": "xkb-Latn-BJ", + "xkc": "xkc-Arab-IR", + "xkd": "xkd-Latn-ID", + "xke": "xke-Latn-ID", + "xkg": "xkg-Latn-ML", + "xkj": "xkj-Arab-IR", + "xkl": "xkl-Latn-ID", + "xkn": "xkn-Latn-ID", + "xkp": "xkp-Arab-IR", + "xkq": "xkq-Latn-ID", + "xkr": "xkr-Latn-BR", + "xks": "xks-Latn-ID", + "xkt": "xkt-Latn-GH", + "xku": "xku-Latn-CG", + "xkv": "xkv-Latn-BW", + "xkw": "xkw-Latn-ID", + "xkx": "xkx-Latn-PG", + "xky": "xky-Latn-MY", + "xkz": "xkz-Latn-BT", + "xla": "xla-Latn-ZZ", + "xlc": "xlc-Lyci-TR", + "xld": "xld-Lydi-TR", + "xly": "xly-Elym-IR", + "xma": "xma-Latn-SO", + "xmb": "xmb-Latn-CM", + "xmc": "xmc-Latn-MZ", + "xmd": "xmd-Latn-CM", + "xmf": "xmf-Geor-GE", + "xmg": "xmg-Latn-CM", + "xmh": "xmh-Latn-AU", + "xmj": "xmj-Latn-CM", + "xmm": "xmm-Latn-ID", + "xmn": "xmn-Mani-CN", + "xmo": "xmo-Latn-BR", + "xmp": "xmp-Latn-AU", + "xmq": "xmq-Latn-AU", + "xmr": "xmr-Merc-SD", + "xmt": "xmt-Latn-ID", + "xmu": "xmu-Latn-AU", + "xmv": "xmv-Latn-MG", + "xmw": "xmw-Latn-MG", + "xmx": "xmx-Latn-ID", + "xmy": "xmy-Latn-AU", + "xmz": "xmz-Latn-ID", + "xna": "xna-Narb-SA", + "xnb": "xnb-Latn-TW", + "xni": "xni-Latn-AU", + "xnj": "xnj-Latn-TZ", + "xnk": "xnk-Latn-AU", + "xnm": "xnm-Latn-AU", + "xnn": "xnn-Latn-PH", + "xnq": "xnq-Latn-MZ", + "xnr": "xnr-Deva-IN", + "xnt": "xnt-Latn-US", + "xnu": "xnu-Latn-AU", + "xny": "xny-Latn-AU", + "xnz": "xnz-Latn-EG", + "xnz-Arab": "xnz-Arab-EG", + "xoc": "xoc-Latn-NG", + "xod": "xod-Latn-ID", + "xog": "xog-Latn-UG", + "xoi": "xoi-Latn-PG", + "xok": "xok-Latn-BR", + "xom": "xom-Latn-SD", + "xom-Ethi": "xom-Ethi-ET", + "xon": "xon-Latn-ZZ", + "xoo": "xoo-Latn-BR", + "xop": "xop-Latn-PG", + "xor": "xor-Latn-BR", + "xow": "xow-Latn-PG", + "xpa": "xpa-Latn-AU", + "xpb": "xpb-Latn-AU", + "xpd": "xpd-Latn-AU", + "xpf": "xpf-Latn-AU", + "xpg": "xpg-Grek-TR", + "xph": "xph-Latn-AU", + "xpi": "xpi-Ogam-GB", + "xpj": "xpj-Latn-AU", + "xpk": "xpk-Latn-BR", + "xpl": "xpl-Latn-AU", + "xpm": "xpm-Cyrl-RU", + "xpn": "xpn-Latn-BR", + "xpo": "xpo-Latn-MX", + "xpq": "xpq-Latn-US", + "xpr": "xpr-Prti-IR", + "xpt": "xpt-Latn-AU", + "xpv": "xpv-Latn-AU", + "xpw": "xpw-Latn-AU", + "xpx": "xpx-Latn-AU", + "xpz": "xpz-Latn-AU", + "xra": "xra-Latn-BR", + "xrb": "xrb-Latn-ZZ", + "xrd": "xrd-Latn-AU", + "xre": "xre-Latn-BR", + "xrg": "xrg-Latn-AU", + "xri": "xri-Latn-BR", + "xrm": "xrm-Cyrl-RU", + "xrn": "xrn-Cyrl-RU", + "xrr": "xrr-Latn-IT", + "xru": "xru-Latn-AU", + "xrw": "xrw-Latn-PG", + "xsa": "xsa-Sarb-YE", + "xsb": "xsb-Latn-PH", + "xse": "xse-Latn-ID", + "xsh": "xsh-Latn-NG", + "xsi": "xsi-Latn-ZZ", + "xsm": "xsm-Latn-ZZ", + "xsn": "xsn-Latn-NG", + "xsp": "xsp-Latn-PG", + "xsq": "xsq-Latn-MZ", + "xsr": "xsr-Deva-NP", + "xss": "xss-Cyrl-RU", + "xsu": "xsu-Latn-VE", + "xsy": "xsy-Latn-TW", + "xta": "xta-Latn-MX", + "xtb": "xtb-Latn-MX", + "xtc": "xtc-Latn-SD", + "xtd": "xtd-Latn-MX", + "xte": "xte-Latn-ID", + "xth": "xth-Latn-AU", + "xti": "xti-Latn-MX", + "xtj": "xtj-Latn-MX", + "xtl": "xtl-Latn-MX", + "xtm": "xtm-Latn-MX", + "xtn": "xtn-Latn-MX", + "xtp": "xtp-Latn-MX", + "xts": "xts-Latn-MX", + "xtt": "xtt-Latn-MX", + "xtu": "xtu-Latn-MX", + "xtv": "xtv-Latn-AU", + "xtw": "xtw-Latn-BR", + "xty": "xty-Latn-MX", + "xub": "xub-Taml-IN", + "xub-Knda": "xub-Knda-IN", + "xub-Mlym": "xub-Mlym-IN", + "xud": "xud-Latn-AU", + "xuj": "xuj-Taml-IN", + "xul": "xul-Latn-AU", + "xum": "xum-Latn-IT", + "xum-Ital": "xum-Ital-IT", + "xun": "xun-Latn-AU", + "xuo": "xuo-Latn-TD", + "xut": "xut-Latn-AU", + "xuu": "xuu-Latn-NA", + "xve": "xve-Ital-IT", + "xvi": "xvi-Arab-AF", + "xvn": "xvn-Latn-ES", + "xvo": "xvo-Latn-IT", + "xvs": "xvs-Latn-IT", + "xwa": "xwa-Latn-BR", + "xwd": "xwd-Latn-AU", + "xwe": "xwe-Latn-ZZ", + "xwj": "xwj-Latn-AU", + "xwk": "xwk-Latn-AU", + "xwl": "xwl-Latn-BJ", + "xwo": "xwo-Cyrl-RU", + "xwr": "xwr-Latn-ID", + "xwt": "xwt-Latn-AU", + "xww": "xww-Latn-AU", + "xxb": "xxb-Latn-GH", + "xxk": "xxk-Latn-ID", + "xxm": "xxm-Latn-AU", + "xxr": "xxr-Latn-BR", + "xxt": "xxt-Latn-ID", + "xya": "xya-Latn-AU", + "xyb": "xyb-Latn-AU", + "xyj": "xyj-Latn-AU", + "xyk": "xyk-Latn-AU", + "xyl": "xyl-Latn-BR", + "xyt": "xyt-Latn-AU", + "xyy": "xyy-Latn-AU", + "xzh": "xzh-Marc-CN", + "xzp": "xzp-Latn-MX", + "yaa": "yaa-Latn-PE", + "yab": "yab-Latn-BR", + "yac": "yac-Latn-ID", + "yad": "yad-Latn-PE", + "yae": "yae-Latn-VE", + "yaf": "yaf-Latn-CD", + "yag": "yag-Latn-CL", + "yai": "yai-Cyrl-TJ", + "yaj": "yaj-Latn-CF", + "yak": "yak-Latn-US", + "yal": "yal-Latn-GN", + "yal-Arab": "yal-Arab-GN", + "yam": "yam-Latn-ZZ", + "yan": "yan-Latn-NI", + "yao": "yao-Latn-MZ", + "yap": "yap-Latn-FM", + "yaq": "yaq-Latn-MX", + "yar": "yar-Latn-VE", + "yas": "yas-Latn-ZZ", + "yat": "yat-Latn-ZZ", + "yau": "yau-Latn-VE", + "yav": "yav-Latn-CM", + "yaw": "yaw-Latn-BR", + "yax": "yax-Latn-AO", + "yay": "yay-Latn-ZZ", + "yaz": "yaz-Latn-ZZ", + "yba": "yba-Latn-ZZ", + "ybb": "ybb-Latn-CM", + "ybe": "ybe-Latn-CN", + "ybe-Ougr": "ybe-Ougr-CN", + "ybh": "ybh-Deva-NP", + "ybi": "ybi-Deva-NP", + "ybj": "ybj-Latn-NG", + "ybl": "ybl-Latn-NG", + "ybm": "ybm-Latn-PG", + "ybn": "ybn-Latn-BR", + "ybo": "ybo-Latn-PG", + "ybx": "ybx-Latn-PG", + "yby": "yby-Latn-ZZ", + "ycl": "ycl-Latn-CN", + "ycn": "ycn-Latn-CO", + "yda": "yda-Latn-AU", + "yde": "yde-Latn-PG", + "ydg": "ydg-Arab-PK", + "ydk": "ydk-Latn-PG", + "yea": "yea-Mlym-IN", + "yea-Knda": "yea-Knda-IN", + "yec": "yec-Latn-DE", + "yee": "yee-Latn-PG", + "yei": "yei-Latn-CM", + "yej": "yej-Grek-IL", + "yel": "yel-Latn-CD", + "yer": "yer-Latn-ZZ", + "yes": "yes-Latn-NG", + "yet": "yet-Latn-ID", + "yeu": "yeu-Telu-IN", + "yev": "yev-Latn-PG", + "yey": "yey-Latn-BW", + "yga": "yga-Latn-AU", + "ygi": "ygi-Latn-AU", + "ygl": "ygl-Latn-PG", + "ygm": "ygm-Latn-PG", + "ygp": "ygp-Plrd-CN", + "ygr": "ygr-Latn-ZZ", + "ygu": "ygu-Latn-AU", + "ygw": "ygw-Latn-ZZ", + "yhd": "yhd-Hebr-IL", + "yi": "yi-Hebr-001", + "yia": "yia-Latn-AU", + "yig": "yig-Yiii-CN", + "yih": "yih-Hebr-DE", + "yii": "yii-Latn-AU", + "yij": "yij-Latn-AU", + "yil": "yil-Latn-AU", + "yim": "yim-Latn-IN", + "yir": "yir-Latn-ID", + "yis": "yis-Latn-PG", + "yiv": "yiv-Yiii-CN", + "yka": "yka-Latn-PH", + "yka-Arab": "yka-Arab-PH", + "ykg": "ykg-Cyrl-RU", + "yki": "yki-Latn-ID", + "ykk": "ykk-Latn-PG", + "ykm": "ykm-Latn-PG", + "yko": "yko-Latn-ZZ", + "ykr": "ykr-Latn-PG", + "yky": "yky-Latn-CF", + "yla": "yla-Latn-PG", + "ylb": "ylb-Latn-PG", + "yle": "yle-Latn-ZZ", + "ylg": "ylg-Latn-ZZ", + "yli": "yli-Latn-ID", + "yll": "yll-Latn-ZZ", + "ylr": "ylr-Latn-AU", + "ylu": "ylu-Latn-PG", + "yly": "yly-Latn-NC", + "ymb": "ymb-Latn-PG", + "yme": "yme-Latn-PE", + "ymg": "ymg-Latn-CD", + "ymk": "ymk-Latn-MZ", + "ymk-Arab": "ymk-Arab-MZ", + "yml": "yml-Latn-ZZ", + "ymm": "ymm-Latn-SO", + "ymn": "ymn-Latn-ID", + "ymo": "ymo-Latn-PG", + "ymp": "ymp-Latn-PG", + "yna": "yna-Plrd-CN", + "ynd": "ynd-Latn-AU", + "yng": "yng-Latn-CD", + "ynk": "ynk-Cyrl-RU", + "ynl": "ynl-Latn-PG", + "ynq": "ynq-Latn-NG", + "yns": "yns-Latn-CD", + "ynu": "ynu-Latn-CO", + "yo": "yo-Latn-NG", + "yob": "yob-Latn-PG", + "yog": "yog-Latn-PH", + "yoi": "yoi-Jpan-JP", + "yok": "yok-Latn-US", + "yol": "yol-Latn-GB", + "yom": "yom-Latn-CD", + "yon": "yon-Latn-ZZ", + "yot": "yot-Latn-NG", + "yoy": "yoy-Thai-TH", + "yra": "yra-Latn-PG", + "yrb": "yrb-Latn-ZZ", + "yre": "yre-Latn-ZZ", + "yrk": "yrk-Cyrl-RU", + "yrl": "yrl-Latn-BR", + "yrm": "yrm-Latn-AU", + "yro": "yro-Latn-BR", + "yrs": "yrs-Latn-ID", + "yrw": "yrw-Latn-PG", + "yry": "yry-Latn-AU", + "ysd": "ysd-Yiii-CN", + "ysn": "ysn-Yiii-CN", + "ysp": "ysp-Yiii-CN", + "ysr": "ysr-Cyrl-RU", + "yss": "yss-Latn-ZZ", + "ysy": "ysy-Plrd-CN", + "ytw": "ytw-Latn-PG", + "yty": "yty-Latn-AU", + "yua": "yua-Latn-MX", + "yub": "yub-Latn-AU", + "yuc": "yuc-Latn-US", + "yud": "yud-Hebr-IL", + "yue": "yue-Hant-HK", + "yue-CN": "yue-Hans-CN", + "yue-Hans": "yue-Hans-CN", + "yuf": "yuf-Latn-US", + "yug": "yug-Cyrl-RU", + "yui": "yui-Latn-CO", + "yuj": "yuj-Latn-ZZ", + "yul": "yul-Latn-CF", + "yum": "yum-Latn-US", + "yun": "yun-Latn-NG", + "yup": "yup-Latn-CO", + "yuq": "yuq-Latn-BO", + "yur": "yur-Latn-US", + "yut": "yut-Latn-ZZ", + "yuw": "yuw-Latn-ZZ", + "yux": "yux-Cyrl-RU", + "yuz": "yuz-Latn-BO", + "yva": "yva-Latn-ID", + "yvt": "yvt-Latn-VE", + "ywa": "ywa-Latn-PG", + "ywg": "ywg-Latn-AU", + "ywn": "ywn-Latn-BR", + "ywq": "ywq-Plrd-CN", + "ywq-Yiii": "ywq-Yiii-CN", + "ywr": "ywr-Latn-AU", + "ywu": "ywu-Plrd-CN", + "ywu-Yiii": "ywu-Yiii-CN", + "yww": "yww-Latn-AU", + "yxa": "yxa-Latn-AU", + "yxg": "yxg-Latn-AU", + "yxl": "yxl-Latn-AU", + "yxm": "yxm-Latn-AU", + "yxu": "yxu-Latn-AU", + "yxy": "yxy-Latn-AU", + "yyr": "yyr-Latn-AU", + "yyu": "yyu-Latn-PG", + "za": "za-Latn-CN", + "zaa": "zaa-Latn-MX", + "zab": "zab-Latn-MX", + "zac": "zac-Latn-MX", + "zad": "zad-Latn-MX", + "zae": "zae-Latn-MX", + "zaf": "zaf-Latn-MX", + "zag": "zag-Latn-SD", + "zah": "zah-Latn-NG", + "zaj": "zaj-Latn-TZ", + "zak": "zak-Latn-TZ", + "zam": "zam-Latn-MX", + "zao": "zao-Latn-MX", + "zap": "zap-Latn-MX", + "zaq": "zaq-Latn-MX", + "zar": "zar-Latn-MX", + "zas": "zas-Latn-MX", + "zat": "zat-Latn-MX", + "zau": "zau-Tibt-IN", + "zau-Arab": "zau-Arab-IN", + "zav": "zav-Latn-MX", + "zaw": "zaw-Latn-MX", + "zax": "zax-Latn-MX", + "zay": "zay-Latn-ET", + "zay-Ethi": "zay-Ethi-ET", + "zaz": "zaz-Latn-NG", + "zba": "zba-Arab-001", + "zbc": "zbc-Latn-MY", + "zbe": "zbe-Latn-MY", + "zbt": "zbt-Latn-ID", + "zbu": "zbu-Latn-NG", + "zbw": "zbw-Latn-MY", + "zca": "zca-Latn-MX", + "zch": "zch-Hani-CN", + "zdj": "zdj-Arab-KM", + "zea": "zea-Latn-NL", + "zeg": "zeg-Latn-PG", + "zeh": "zeh-Hani-CN", + "zen": "zen-Tfng-MR", + "zen-Arab": "zen-Arab-MR", + "zga": "zga-Latn-TZ", + "zgb": "zgb-Hani-CN", + "zgh": "zgh-Tfng-MA", + "zgm": "zgm-Hani-CN", + "zgn": "zgn-Hani-CN", + "zgr": "zgr-Latn-PG", + "zh": "zh-Hans-CN", + "zh-AU": "zh-Hant-AU", + "zh-BN": "zh-Hant-BN", + "zh-Bopo": "zh-Bopo-TW", + "zh-GB": "zh-Hant-GB", + "zh-GF": "zh-Hant-GF", + "zh-HK": "zh-Hant-HK", + "zh-Hanb": "zh-Hanb-TW", + "zh-Hant": "zh-Hant-TW", + "zh-ID": "zh-Hant-ID", + "zh-MO": "zh-Hant-MO", + "zh-PA": "zh-Hant-PA", + "zh-PF": "zh-Hant-PF", + "zh-PH": "zh-Hant-PH", + "zh-SR": "zh-Hant-SR", + "zh-TH": "zh-Hant-TH", + "zh-TW": "zh-Hant-TW", + "zh-US": "zh-Hant-US", + "zh-VN": "zh-Hant-VN", + "zhd": "zhd-Hani-CN", + "zhd-Latn": "zhd-Latn-VN", + "zhi": "zhi-Latn-NG", + "zhn": "zhn-Latn-CN", + "zhn-Hani": "zhn-Hani-CN", + "zhw": "zhw-Latn-CM", + "zhx": "zhx-Nshu-CN", + "zia": "zia-Latn-ZZ", + "zik": "zik-Latn-PG", + "zil": "zil-Latn-GN", + "zim": "zim-Latn-TD", + "zin": "zin-Latn-TZ", + "ziw": "ziw-Latn-TZ", + "ziz": "ziz-Latn-NG", + "zka": "zka-Latn-ID", + "zkb": "zkb-Cyrl-RU", + "zkd": "zkd-Latn-MM", + "zko": "zko-Cyrl-RU", + "zkp": "zkp-Latn-BR", + "zkt": "zkt-Kits-CN", + "zku": "zku-Latn-AU", + "zkz": "zkz-Cyrl-RU", + "zla": "zla-Latn-CD", + "zlj": "zlj-Hani-CN", + "zlj-Latn": "zlj-Latn-CN", + "zlm": "zlm-Latn-TG", + "zln": "zln-Hani-CN", + "zlq": "zlq-Hani-CN", + "zma": "zma-Latn-AU", + "zmb": "zmb-Latn-CD", + "zmc": "zmc-Latn-AU", + "zmd": "zmd-Latn-AU", + "zme": "zme-Latn-AU", + "zmf": "zmf-Latn-CD", + "zmg": "zmg-Latn-AU", + "zmh": "zmh-Latn-PG", + "zmi": "zmi-Latn-MY", + "zmj": "zmj-Latn-AU", + "zmk": "zmk-Latn-AU", + "zml": "zml-Latn-AU", + "zmm": "zmm-Latn-AU", + "zmn": "zmn-Latn-GA", + "zmo": "zmo-Latn-SD", + "zmp": "zmp-Latn-CD", + "zmq": "zmq-Latn-CD", + "zmr": "zmr-Latn-AU", + "zms": "zms-Latn-CD", + "zmt": "zmt-Latn-AU", + "zmu": "zmu-Latn-AU", + "zmv": "zmv-Latn-AU", + "zmw": "zmw-Latn-CD", + "zmx": "zmx-Latn-CG", + "zmy": "zmy-Latn-AU", + "zmz": "zmz-Latn-CD", + "zna": "zna-Latn-TD", + "zne": "zne-Latn-ZZ", + "zng": "zng-Latn-VN", + "znk": "znk-Latn-AU", + "zns": "zns-Latn-NG", + "zoc": "zoc-Latn-MX", + "zoh": "zoh-Latn-MX", + "zom": "zom-Latn-IN", + "zoo": "zoo-Latn-MX", + "zoq": "zoq-Latn-MX", + "zor": "zor-Latn-MX", + "zos": "zos-Latn-MX", + "zpa": "zpa-Latn-MX", + "zpb": "zpb-Latn-MX", + "zpc": "zpc-Latn-MX", + "zpd": "zpd-Latn-MX", + "zpe": "zpe-Latn-MX", + "zpf": "zpf-Latn-MX", + "zpg": "zpg-Latn-MX", + "zph": "zph-Latn-MX", + "zpi": "zpi-Latn-MX", + "zpj": "zpj-Latn-MX", + "zpk": "zpk-Latn-MX", + "zpl": "zpl-Latn-MX", + "zpm": "zpm-Latn-MX", + "zpn": "zpn-Latn-MX", + "zpo": "zpo-Latn-MX", + "zpp": "zpp-Latn-MX", + "zpq": "zpq-Latn-MX", + "zpr": "zpr-Latn-MX", + "zps": "zps-Latn-MX", + "zpt": "zpt-Latn-MX", + "zpu": "zpu-Latn-MX", + "zpv": "zpv-Latn-MX", + "zpw": "zpw-Latn-MX", + "zpx": "zpx-Latn-MX", + "zpy": "zpy-Latn-MX", + "zpz": "zpz-Latn-MX", + "zqe": "zqe-Hani-CN", + "zqe-Latn": "zqe-Latn-CN", + "zrn": "zrn-Latn-TD", + "zro": "zro-Latn-EC", + "zrp": "zrp-Hebr-FR", + "zrs": "zrs-Latn-ID", + "zsa": "zsa-Latn-PG", + "zsr": "zsr-Latn-MX", + "zsu": "zsu-Latn-PG", + "zte": "zte-Latn-MX", + "ztg": "ztg-Latn-MX", + "ztl": "ztl-Latn-MX", + "ztm": "ztm-Latn-MX", + "ztn": "ztn-Latn-MX", + "ztp": "ztp-Latn-MX", + "ztq": "ztq-Latn-MX", + "zts": "zts-Latn-MX", + "ztt": "ztt-Latn-MX", + "ztu": "ztu-Latn-MX", + "ztx": "ztx-Latn-MX", + "zty": "zty-Latn-MX", + "zu": "zu-Latn-ZA", + "zua": "zua-Latn-NG", + "zuh": "zuh-Latn-PG", + "zum": "zum-Arab-OM", + "zun": "zun-Latn-US", + "zuy": "zuy-Latn-CM", + "zyg": "zyg-Hani-CN", + "zyj": "zyj-Latn-CN", + "zyj-Hani": "zyj-Hani-CN", + "zyn": "zyn-Hani-CN", + "zyp": "zyp-Latn-MM", + "zza": "zza-Latn-TR", + "zzj": "zzj-Hani-CN", +}; + +// Extracted from likelySubtags.xml. +// Derived from CLDR Supplemental Data, version 43. +// https://unicode.org/Public/cldr/43/cldr-common-43.0.zip +var minLikelySubtags = { + "aa-Latn-DJ": "aa-DJ", + "aa-Latn-ET": "aa", + "aaa-Latn-NG": "aaa", + "aab-Latn-NG": "aab", + "aac-Latn-PG": "aac", + "aad-Latn-PG": "aad", + "aae-Grek-IT": "aae-Grek", + "aae-Latn-IT": "aae", + "aaf-Arab-IN": "aaf-Arab", + "aaf-Mlym-IN": "aaf", + "aag-Latn-PG": "aag", + "aah-Latn-PG": "aah", + "aai-Latn-ZZ": "aai", + "aak-Latn-ZZ": "aak", + "aal-Latn-CM": "aal", + "aan-Latn-BR": "aan", + "aao-Arab-DZ": "aao", + "aap-Latn-BR": "aap", + "aaq-Latn-US": "aaq", + "aas-Latn-TZ": "aas", + "aat-Grek-GR": "aat", + "aau-Latn-ZZ": "aau", + "aaw-Latn-PG": "aaw", + "aax-Latn-ID": "aax", + "aaz-Latn-ID": "aaz", + "ab-Cyrl-GE": "ab", + "aba-Latn-CI": "aba", + "abb-Latn-CM": "abb", + "abc-Latn-PH": "abc", + "abd-Latn-PH": "abd", + "abe-Latn-CA": "abe", + "abf-Latn-MY": "abf", + "abg-Latn-PG": "abg", + "abh-Arab-TJ": "abh", + "abi-Latn-ZZ": "abi", + "abl-Latn-ID": "abl-Latn", + "abl-Rjng-ID": "abl", + "abm-Latn-NG": "abm", + "abn-Latn-NG": "abn", + "abo-Latn-NG": "abo", + "abp-Latn-PH": "abp", + "abq-Cyrl-ZZ": "abq", + "abr-Latn-GH": "abr", + "abs-Latn-ID": "abs", + "abt-Latn-ZZ": "abt", + "abu-Latn-CI": "abu", + "abv-Arab-BH": "abv", + "abw-Latn-PG": "abw", + "abx-Latn-PH": "abx", + "aby-Latn-ZZ": "aby", + "abz-Latn-ID": "abz", + "aca-Latn-CO": "aca", + "acb-Latn-NG": "acb", + "acd-Latn-ZZ": "acd", + "ace-Latn-ID": "ace", + "acf-Latn-LC": "acf", + "ach-Latn-UG": "ach", + "acm-Arab-IQ": "acm", + "acn-Latn-CN": "acn", + "acp-Latn-NG": "acp", + "acq-Arab-YE": "acq", + "acr-Latn-GT": "acr", + "acs-Latn-BR": "acs", + "act-Latn-NL": "act", + "acu-Latn-EC": "acu", + "acv-Latn-US": "acv", + "acw-Arab-SA": "acw", + "acx-Arab-OM": "acx", + "acy-Arab-CY": "acy-Arab", + "acy-Grek-CY": "acy-Grek", + "acy-Latn-CY": "acy", + "acz-Latn-SD": "acz", + "ada-Latn-GH": "ada", + "adb-Latn-TL": "adb", + "add-Latn-CM": "add", + "ade-Latn-ZZ": "ade", + "adf-Arab-OM": "adf", + "adg-Latn-AU": "adg", + "adh-Latn-UG": "adh", + "adi-Latn-IN": "adi", + "adi-Tibt-CN": "adi-Tibt", + "adj-Latn-ZZ": "adj", + "adl-Latn-IN": "adl", + "adn-Latn-ID": "adn", + "ado-Latn-PG": "ado", + "adq-Latn-GH": "adq", + "adr-Latn-ID": "adr", + "adt-Latn-AU": "adt", + "adu-Latn-NG": "adu", + "adw-Latn-BR": "adw", + "adx-Tibt-CN": "adx", + "ady-Cyrl-RU": "ady", + "adz-Latn-ZZ": "adz", + "ae-Avst-IR": "ae", + "aea-Latn-AU": "aea", + "aeb-Arab-TN": "aeb", + "aec-Arab-EG": "aec", + "aee-Arab-AF": "aee", + "aek-Latn-NC": "aek", + "ael-Latn-CM": "ael", + "aem-Latn-VN": "aem", + "aeq-Arab-PK": "aeq", + "aer-Latn-AU": "aer", + "aeu-Latn-CN": "aeu", + "aew-Latn-PG": "aew", + "aey-Latn-ZZ": "aey", + "aez-Latn-PG": "aez", + "af-Latn-NA": "af-NA", + "af-Latn-ZA": "af", + "afb-Arab-KW": "afb", + "afd-Latn-PG": "afd", + "afe-Latn-NG": "afe", + "afh-Latn-GH": "afh", + "afi-Latn-PG": "afi", + "afk-Latn-PG": "afk", + "afn-Latn-NG": "afn", + "afo-Latn-NG": "afo", + "afp-Latn-PG": "afp", + "afs-Latn-MX": "afs", + "afu-Latn-GH": "afu", + "afz-Latn-ID": "afz", + "aga-Latn-PE": "aga", + "agb-Latn-NG": "agb", + "agc-Latn-ZZ": "agc", + "agd-Latn-ZZ": "agd", + "age-Latn-PG": "age", + "agf-Latn-ID": "agf", + "agg-Latn-ZZ": "agg", + "agh-Latn-CD": "agh", + "agi-Deva-IN": "agi", + "agj-Arab-ET": "agj-Arab", + "agj-Ethi-ET": "agj", + "agk-Latn-PH": "agk", + "agl-Latn-PG": "agl", + "agm-Latn-ZZ": "agm", + "agn-Latn-PH": "agn", + "ago-Latn-ZZ": "ago", + "agq-Latn-CM": "agq", + "agr-Latn-PE": "agr", + "ags-Latn-CM": "ags", + "agt-Latn-PH": "agt", + "agu-Latn-GT": "agu", + "agv-Latn-PH": "agv", + "agw-Latn-SB": "agw", + "agx-Cyrl-RU": "agx", + "agy-Latn-PH": "agy", + "agz-Latn-PH": "agz", + "aha-Latn-ZZ": "aha", + "ahb-Latn-VU": "ahb", + "ahg-Ethi-ET": "ahg", + "ahh-Latn-ID": "ahh", + "ahi-Latn-CI": "ahi", + "ahk-Latn-MM": "ahk", + "ahk-Latn-TH": "ahk-TH", + "ahk-Mymr-MM": "ahk-Mymr", + "ahk-Thai-TH": "ahk-Thai", + "ahl-Latn-ZZ": "ahl", + "ahm-Latn-CI": "ahm", + "ahn-Latn-NG": "ahn", + "aho-Ahom-IN": "aho", + "ahp-Latn-CI": "ahp", + "ahr-Deva-IN": "ahr", + "ahs-Latn-NG": "ahs", + "aht-Latn-US": "aht", + "aia-Latn-SB": "aia", + "aib-Arab-CN": "aib", + "aic-Latn-PG": "aic", + "aid-Latn-AU": "aid", + "aie-Latn-PG": "aie", + "aif-Latn-PG": "aif", + "aig-Latn-AG": "aig", + "aij-Hebr-IL": "aij", + "aik-Latn-NG": "aik", + "ail-Latn-PG": "ail", + "aim-Latn-IN": "aim", + "ain-Kana-JP": "ain", + "ain-Latn-JP": "ain-Latn", + "aio-Mymr-IN": "aio", + "aip-Latn-ID": "aip", + "aiq-Arab-AF": "aiq", + "air-Latn-ID": "air", + "ait-Latn-BR": "ait", + "aiw-Arab-ET": "aiw-Arab", + "aiw-Ethi-ET": "aiw-Ethi", + "aiw-Latn-ET": "aiw", + "aix-Latn-PG": "aix", + "aiy-Latn-CF": "aiy", + "aja-Latn-SS": "aja", + "ajg-Latn-ZZ": "ajg", + "aji-Latn-NC": "aji", + "ajn-Latn-AU": "ajn", + "ajp-Arab-JO": "ajp", + "ajw-Latn-NG": "ajw", + "ajz-Latn-IN": "ajz", + "ak-Latn-GH": "ak", + "akb-Batk-ID": "akb-Batk", + "akb-Latn-ID": "akb", + "akc-Latn-ID": "akc", + "akd-Latn-NG": "akd", + "ake-Latn-GY": "ake", + "akf-Latn-NG": "akf", + "akg-Latn-ID": "akg", + "akh-Latn-PG": "akh", + "aki-Latn-PG": "aki", + "akk-Xsux-IQ": "akk", + "akl-Latn-PH": "akl", + "ako-Latn-SR": "ako", + "akp-Latn-GH": "akp", + "akq-Latn-PG": "akq", + "akr-Latn-VU": "akr", + "aks-Latn-TG": "aks", + "akt-Latn-PG": "akt", + "aku-Latn-CM": "aku", + "akv-Cyrl-RU": "akv", + "akw-Latn-CG": "akw", + "akz-Latn-US": "akz", + "ala-Latn-ZZ": "ala", + "alc-Latn-CL": "alc", + "ald-Latn-CI": "ald", + "ale-Latn-US": "ale", + "alf-Latn-NG": "alf", + "alh-Latn-AU": "alh", + "ali-Latn-ZZ": "ali", + "alj-Latn-PH": "alj", + "alk-Laoo-LA": "alk", + "all-Mlym-IN": "all", + "alm-Latn-VU": "alm", + "aln-Latn-XK": "aln", + "alo-Latn-ID": "alo", + "alp-Latn-ID": "alp", + "alq-Latn-CA": "alq", + "alr-Cyrl-RU": "alr", + "alt-Cyrl-RU": "alt", + "alu-Latn-SB": "alu", + "alw-Ethi-ET": "alw", + "alx-Latn-PG": "alx", + "aly-Latn-AU": "aly", + "alz-Latn-CD": "alz", + "am-Ethi-ET": "am", + "ama-Latn-BR": "ama", + "amb-Latn-NG": "amb", + "amc-Latn-PE": "amc", + "ame-Latn-PE": "ame", + "amf-Ethi-ET": "amf-Ethi", + "amf-Latn-ET": "amf", + "amg-Latn-AU": "amg", + "ami-Latn-TW": "ami", + "amj-Latn-TD": "amj", + "amk-Latn-ID": "amk", + "amm-Latn-ZZ": "amm", + "amn-Latn-ZZ": "amn", + "amo-Latn-NG": "amo", + "amp-Latn-ZZ": "amp", + "amq-Latn-ID": "amq", + "amr-Latn-PE": "amr", + "ams-Jpan-JP": "ams", + "amt-Latn-PG": "amt", + "amu-Latn-MX": "amu", + "amv-Latn-ID": "amv", + "amw-Arab-SY": "amw-Arab", + "amw-Armi-SY": "amw-Armi", + "amw-Latn-SY": "amw-Latn", + "amw-Syrc-SY": "amw", + "amx-Latn-AU": "amx", + "amy-Latn-AU": "amy", + "amz-Latn-AU": "amz", + "an-Latn-ES": "an", + "ana-Latn-CO": "ana", + "anb-Latn-PE": "anb", + "anc-Latn-ZZ": "anc", + "and-Latn-ID": "and", + "ane-Latn-NC": "ane", + "anf-Latn-GH": "anf", + "ang-Latn-GB": "ang", + "anh-Latn-PG": "anh", + "ani-Cyrl-RU": "ani", + "anj-Latn-PG": "anj", + "ank-Latn-ZZ": "ank", + "anl-Latn-MM": "anl", + "anm-Latn-IN": "anm", + "ann-Latn-NG": "ann", + "ano-Latn-CO": "ano", + "anp-Deva-IN": "anp", + "anr-Deva-IN": "anr", + "ans-Latn-CO": "ans", + "ant-Latn-AU": "ant", + "anu-Arab-SS": "anu-Arab", + "anu-Ethi-ET": "anu", + "anu-Latn-SS": "anu-Latn", + "anv-Latn-CM": "anv", + "anw-Latn-NG": "anw", + "anx-Latn-PG": "anx", + "any-Latn-ZZ": "any", + "anz-Latn-PG": "anz", + "aoa-Latn-ST": "aoa", + "aob-Latn-PG": "aob", + "aoc-Latn-VE": "aoc", + "aod-Latn-PG": "aod", + "aoe-Latn-PG": "aoe", + "aof-Latn-PG": "aof", + "aog-Latn-PG": "aog", + "aoi-Latn-AU": "aoi", + "aoj-Latn-ZZ": "aoj", + "aok-Latn-NC": "aok", + "aol-Latn-ID": "aol", + "aom-Latn-ZZ": "aom", + "aon-Latn-PG": "aon", + "aor-Latn-VU": "aor", + "aos-Latn-ID": "aos", + "aot-Beng-BD": "aot", + "aot-Latn-IN": "aot-Latn", + "aox-Latn-GY": "aox", + "aoz-Latn-ID": "aoz", + "apb-Latn-SB": "apb", + "apc-Arab-SY": "apc", + "apc-Arab-TR": "apc-TR", + "apd-Arab-TG": "apd", + "ape-Latn-ZZ": "ape", + "apf-Latn-PH": "apf", + "apg-Latn-ID": "apg", + "aph-Deva-NP": "aph", + "api-Latn-BR": "api", + "apj-Latn-US": "apj", + "apk-Latn-US": "apk", + "apl-Latn-US": "apl", + "apm-Latn-US": "apm", + "apn-Latn-BR": "apn", + "apo-Latn-PG": "apo", + "app-Latn-VU": "app", + "apr-Latn-ZZ": "apr", + "aps-Latn-ZZ": "aps", + "apt-Latn-IN": "apt", + "apu-Latn-BR": "apu", + "apv-Latn-BR": "apv", + "apw-Latn-US": "apw", + "apx-Latn-ID": "apx", + "apy-Latn-BR": "apy", + "apz-Latn-ZZ": "apz", + "aqc-Cyrl-RU": "aqc", + "aqd-Latn-ML": "aqd", + "aqg-Latn-NG": "aqg", + "aqk-Latn-NG": "aqk", + "aqm-Latn-ID": "aqm", + "aqn-Latn-PH": "aqn", + "aqr-Latn-NC": "aqr", + "aqt-Latn-PY": "aqt", + "aqz-Latn-BR": "aqz", + "ar-Arab-AE": "ar-AE", + "ar-Arab-BH": "ar-BH", + "ar-Arab-DZ": "ar-DZ", + "ar-Arab-EG": "ar", + "ar-Arab-EH": "ar-EH", + "ar-Arab-IQ": "ar-IQ", + "ar-Arab-JO": "ar-JO", + "ar-Arab-KM": "ar-KM", + "ar-Arab-KW": "ar-KW", + "ar-Arab-LB": "ar-LB", + "ar-Arab-LY": "ar-LY", + "ar-Arab-MA": "ar-MA", + "ar-Arab-MR": "ar-MR", + "ar-Arab-OM": "ar-OM", + "ar-Arab-PS": "ar-PS", + "ar-Arab-QA": "ar-QA", + "ar-Arab-SA": "ar-SA", + "ar-Arab-SD": "ar-SD", + "ar-Arab-SY": "ar-SY", + "ar-Arab-TN": "ar-TN", + "ar-Arab-YE": "ar-YE", + "arc-Armi-IR": "arc", + "arc-Elym-IR": "arc-Elym", + "arc-Nbat-JO": "arc-Nbat", + "arc-Palm-SY": "arc-Palm", + "ard-Latn-AU": "ard", + "are-Latn-AU": "are", + "arh-Latn-ZZ": "arh", + "ari-Latn-US": "ari", + "arj-Latn-BR": "arj", + "ark-Latn-BR": "ark", + "arl-Latn-PE": "arl", + "arn-Latn-CL": "arn", + "aro-Latn-BO": "aro", + "arp-Latn-US": "arp", + "arq-Arab-DZ": "arq", + "arr-Latn-BR": "arr", + "ars-Arab-SA": "ars", + "aru-Latn-BR": "aru", + "arw-Latn-SR": "arw", + "arx-Latn-BR": "arx", + "ary-Arab-MA": "ary", + "arz-Arab-EG": "arz", + "as-Beng-IN": "as", + "asa-Latn-TZ": "asa", + "asb-Latn-CA": "asb", + "asc-Latn-ID": "asc", + "ase-Sgnw-US": "ase", + "asg-Latn-ZZ": "asg", + "ash-Latn-PE": "ash", + "asi-Latn-ID": "asi", + "asj-Latn-CM": "asj", + "ask-Arab-AF": "ask", + "asl-Latn-ID": "asl", + "asn-Latn-BR": "asn", + "aso-Latn-ZZ": "aso", + "ass-Latn-CM": "ass", + "ast-Latn-ES": "ast", + "asu-Latn-BR": "asu", + "asv-Latn-CD": "asv", + "asx-Latn-PG": "asx", + "asy-Latn-ID": "asy", + "asz-Latn-ID": "asz", + "ata-Latn-ZZ": "ata", + "atb-Latn-CN": "atb", + "atb-Lisu-CN": "atb-Lisu", + "atc-Latn-PE": "atc", + "atd-Latn-PH": "atd", + "ate-Latn-PG": "ate", + "atg-Latn-ZZ": "atg", + "ati-Latn-CI": "ati", + "atj-Latn-CA": "atj", + "atk-Latn-PH": "atk", + "atl-Latn-PH": "atl", + "atm-Latn-PH": "atm", + "atn-Arab-IR": "atn", + "ato-Latn-CM": "ato", + "atp-Latn-PH": "atp", + "atq-Latn-ID": "atq", + "atr-Latn-BR": "atr", + "ats-Latn-US": "ats", + "att-Latn-PH": "att", + "atu-Latn-SS": "atu", + "atv-Cyrl-RU": "atv", + "atw-Latn-US": "atw", + "atx-Latn-BR": "atx", + "aty-Latn-VU": "aty", + "atz-Latn-PH": "atz", + "aua-Latn-SB": "aua", + "auc-Latn-EC": "auc", + "aud-Latn-SB": "aud", + "aug-Latn-BJ": "aug", + "auh-Latn-ZM": "auh", + "aui-Latn-PG": "aui", + "auj-Arab-LY": "auj", + "auj-Latn-LY": "auj-Latn", + "auj-Tfng-LY": "auj-Tfng", + "auk-Latn-PG": "auk", + "aul-Latn-VU": "aul", + "aum-Latn-NG": "aum", + "aun-Latn-PG": "aun", + "auo-Latn-NG": "auo", + "aup-Latn-PG": "aup", + "auq-Latn-ID": "auq", + "aur-Latn-PG": "aur", + "aut-Latn-PF": "aut", + "auu-Latn-ID": "auu", + "auw-Latn-ID": "auw", + "auy-Latn-ZZ": "auy", + "auz-Arab-UZ": "auz", + "av-Cyrl-RU": "av", + "avb-Latn-PG": "avb", + "avd-Arab-IR": "avd", + "avi-Latn-CI": "avi", + "avk-Latn-001": "avk", + "avl-Arab-ZZ": "avl", + "avm-Latn-AU": "avm", + "avn-Latn-ZZ": "avn", + "avo-Latn-BR": "avo", + "avs-Latn-PE": "avs", + "avt-Latn-ZZ": "avt", + "avu-Latn-ZZ": "avu", + "avv-Latn-BR": "avv", + "awa-Deva-IN": "awa", + "awb-Latn-ZZ": "awb", + "awc-Latn-NG": "awc", + "awe-Latn-BR": "awe", + "awg-Latn-AU": "awg", + "awh-Latn-ID": "awh", + "awi-Latn-PG": "awi", + "awk-Latn-AU": "awk", + "awm-Latn-PG": "awm", + "awn-Ethi-ET": "awn", + "awo-Latn-ZZ": "awo", + "awr-Latn-ID": "awr", + "aws-Latn-ID": "aws", + "awt-Latn-BR": "awt", + "awu-Latn-ID": "awu", + "awv-Latn-ID": "awv", + "aww-Latn-PG": "aww", + "awx-Latn-ZZ": "awx", + "awy-Latn-ID": "awy", + "axb-Latn-AR": "axb", + "axe-Latn-AU": "axe", + "axg-Latn-BR": "axg", + "axk-Latn-CF": "axk", + "axl-Latn-AU": "axl", + "axm-Armn-AM": "axm", + "axx-Latn-NC": "axx", + "ay-Latn-BO": "ay", + "aya-Latn-PG": "aya", + "ayb-Latn-ZZ": "ayb", + "ayc-Latn-PE": "ayc", + "ayd-Latn-AU": "ayd", + "aye-Latn-NG": "aye", + "ayg-Latn-TG": "ayg", + "ayh-Arab-YE": "ayh", + "ayi-Latn-NG": "ayi", + "ayk-Latn-NG": "ayk", + "ayl-Arab-LY": "ayl", + "ayn-Arab-YE": "ayn", + "ayo-Latn-PY": "ayo", + "ayp-Arab-IQ": "ayp", + "ayq-Latn-PG": "ayq", + "ays-Latn-PH": "ays", + "ayt-Latn-PH": "ayt", + "ayu-Latn-NG": "ayu", + "ayz-Latn-ID": "ayz", + "az-Arab-IQ": "az-IQ", + "az-Arab-IR": "az-IR", + "az-Cyrl-RU": "az-RU", + "az-Latn-AZ": "az", + "azb-Arab-IR": "azb", + "azb-Cyrl-AZ": "azb-Cyrl", + "azb-Latn-AZ": "azb-Latn", + "azd-Latn-MX": "azd", + "azg-Latn-MX": "azg", + "azm-Latn-MX": "azm", + "azn-Latn-MX": "azn", + "azo-Latn-CM": "azo", + "azt-Latn-PH": "azt", + "azz-Latn-MX": "azz", + "ba-Cyrl-RU": "ba", + "baa-Latn-SB": "baa", + "bab-Latn-GW": "bab", + "bac-Latn-ID": "bac", + "bae-Latn-VE": "bae", + "baf-Latn-CM": "baf", + "bag-Latn-CM": "bag", + "bah-Latn-BS": "bah", + "baj-Latn-ID": "baj", + "bal-Arab-PK": "bal", + "ban-Bali-ID": "ban-Bali", + "ban-Latn-ID": "ban", + "bao-Latn-CO": "bao", + "bap-Deva-NP": "bap", + "bar-Latn-AT": "bar", + "bas-Latn-CM": "bas", + "bau-Latn-NG": "bau", + "bav-Latn-ZZ": "bav", + "baw-Latn-CM": "baw", + "bax-Bamu-CM": "bax", + "bay-Latn-ID": "bay", + "bba-Latn-ZZ": "bba", + "bbb-Latn-ZZ": "bbb", + "bbc-Batk-ID": "bbc-Batk", + "bbc-Latn-ID": "bbc", + "bbd-Latn-ZZ": "bbd", + "bbe-Latn-CD": "bbe", + "bbf-Latn-PG": "bbf", + "bbg-Latn-GA": "bbg", + "bbi-Latn-CM": "bbi", + "bbj-Latn-CM": "bbj", + "bbk-Latn-CM": "bbk", + "bbl-Geor-GE": "bbl", + "bbm-Latn-CD": "bbm", + "bbn-Latn-PG": "bbn", + "bbo-Latn-BF": "bbo", + "bbp-Latn-ZZ": "bbp", + "bbq-Latn-CM": "bbq", + "bbr-Latn-ZZ": "bbr", + "bbs-Latn-NG": "bbs", + "bbt-Latn-NG": "bbt", + "bbu-Latn-NG": "bbu", + "bbv-Latn-PG": "bbv", + "bbw-Latn-CM": "bbw", + "bbx-Latn-CM": "bbx", + "bby-Latn-CM": "bby", + "bca-Hani-CN": "bca-Hani", + "bca-Latn-CN": "bca", + "bcb-Latn-SN": "bcb", + "bcd-Latn-ID": "bcd", + "bce-Latn-CM": "bce", + "bcf-Latn-ZZ": "bcf", + "bcg-Latn-GN": "bcg", + "bch-Latn-ZZ": "bch", + "bci-Latn-CI": "bci", + "bcj-Latn-AU": "bcj", + "bck-Latn-AU": "bck", + "bcm-Latn-ZZ": "bcm", + "bcn-Latn-ZZ": "bcn", + "bco-Latn-ZZ": "bco", + "bcp-Latn-CD": "bcp", + "bcq-Ethi-ZZ": "bcq", + "bcr-Latn-CA": "bcr", + "bcs-Latn-NG": "bcs", + "bct-Latn-CD": "bct", + "bcu-Latn-ZZ": "bcu", + "bcv-Latn-NG": "bcv", + "bcw-Latn-CM": "bcw", + "bcy-Latn-NG": "bcy", + "bcz-Latn-SN": "bcz", + "bda-Latn-SN": "bda", + "bdb-Latn-ID": "bdb", + "bdc-Latn-CO": "bdc", + "bdd-Latn-ZZ": "bdd", + "bde-Latn-NG": "bde", + "bdf-Latn-PG": "bdf", + "bdg-Latn-MY": "bdg", + "bdh-Latn-SS": "bdh", + "bdi-Latn-SD": "bdi", + "bdj-Latn-SS": "bdj", + "bdk-Latn-AZ": "bdk", + "bdl-Latn-ID": "bdl", + "bdm-Latn-TD": "bdm", + "bdn-Latn-CM": "bdn", + "bdo-Latn-TD": "bdo", + "bdp-Latn-TZ": "bdp", + "bdq-Latn-VN": "bdq", + "bdr-Latn-MY": "bdr", + "bds-Latn-TZ": "bds", + "bdt-Latn-CF": "bdt", + "bdu-Latn-CM": "bdu", + "bdv-Orya-IN": "bdv", + "bdw-Latn-ID": "bdw", + "bdx-Latn-ID": "bdx", + "bdy-Latn-AU": "bdy", + "bdz-Arab-PK": "bdz", + "be-Cyrl-BY": "be", + "bea-Cans-CA": "bea-Cans", + "bea-Latn-CA": "bea", + "beb-Latn-CM": "beb", + "bec-Latn-CM": "bec", + "bed-Latn-ID": "bed", + "bee-Deva-IN": "bee", + "bef-Latn-ZZ": "bef", + "beh-Latn-ZZ": "beh", + "bei-Latn-ID": "bei", + "bej-Arab-SD": "bej", + "bek-Latn-PG": "bek", + "bem-Latn-ZM": "bem", + "beo-Latn-PG": "beo", + "bep-Latn-ID": "bep", + "beq-Latn-CG": "beq", + "bes-Latn-TD": "bes", + "bet-Latn-ZZ": "bet", + "beu-Latn-ID": "beu", + "bev-Latn-CI": "bev", + "bew-Latn-ID": "bew", + "bex-Latn-ZZ": "bex", + "bey-Latn-PG": "bey", + "bez-Latn-TZ": "bez", + "bfa-Arab-SS": "bfa-Arab", + "bfa-Latn-SS": "bfa", + "bfb-Deva-IN": "bfb", + "bfc-Latn-CN": "bfc", + "bfd-Latn-CM": "bfd", + "bfe-Latn-ID": "bfe", + "bff-Latn-CF": "bff", + "bfg-Latn-ID": "bfg", + "bfh-Latn-PG": "bfh", + "bfj-Latn-CM": "bfj", + "bfl-Latn-CF": "bfl", + "bfm-Latn-CM": "bfm", + "bfn-Latn-TL": "bfn", + "bfo-Latn-BF": "bfo", + "bfp-Latn-CM": "bfp", + "bfq-Taml-IN": "bfq", + "bfs-Hani-CN": "bfs-Hani", + "bfs-Latn-CN": "bfs", + "bft-Arab-PK": "bft", + "bfu-Takr-IN": "bfu-Takr", + "bfu-Tibt-IN": "bfu", + "bfw-Orya-IN": "bfw", + "bfx-Latn-PH": "bfx", + "bfy-Deva-IN": "bfy", + "bfz-Deva-IN": "bfz", + "bg-Cyrl-BG": "bg", + "bg-Cyrl-RO": "bg-RO", + "bga-Latn-NG": "bga", + "bgb-Latn-ID": "bgb", + "bgc-Deva-IN": "bgc", + "bgd-Deva-IN": "bgd", + "bgf-Latn-CM": "bgf", + "bgg-Latn-IN": "bgg", + "bgi-Latn-PH": "bgi", + "bgj-Latn-CM": "bgj", + "bgn-Arab-PK": "bgn", + "bgo-Latn-GN": "bgo", + "bgp-Arab-PK": "bgp", + "bgq-Deva-IN": "bgq", + "bgr-Latn-IN": "bgr", + "bgs-Latn-PH": "bgs", + "bgt-Latn-SB": "bgt", + "bgu-Latn-NG": "bgu", + "bgv-Latn-ID": "bgv", + "bgw-Deva-IN": "bgw", + "bgx-Grek-TR": "bgx", + "bgy-Latn-ID": "bgy", + "bgz-Latn-ID": "bgz", + "bha-Deva-IN": "bha", + "bhb-Deva-IN": "bhb", + "bhc-Latn-ID": "bhc", + "bhd-Arab-IN": "bhd-Arab", + "bhd-Deva-IN": "bhd", + "bhd-Takr-IN": "bhd-Takr", + "bhe-Arab-PK": "bhe", + "bhf-Latn-PG": "bhf", + "bhg-Latn-ZZ": "bhg", + "bhh-Cyrl-IL": "bhh", + "bhh-Hebr-IL": "bhh-Hebr", + "bhh-Latn-IL": "bhh-Latn", + "bhi-Deva-IN": "bhi", + "bhj-Deva-NP": "bhj", + "bhl-Latn-ZZ": "bhl", + "bhm-Arab-OM": "bhm", + "bhn-Syrc-GE": "bhn", + "bho-Deva-IN": "bho", + "bho-Deva-MU": "bho-MU", + "bho-Kthi-IN": "bho-Kthi", + "bhp-Latn-ID": "bhp", + "bhq-Latn-ID": "bhq", + "bhr-Latn-MG": "bhr", + "bhs-Latn-CM": "bhs", + "bht-Deva-IN": "bht-Deva", + "bht-Latn-IN": "bht-Latn", + "bht-Takr-IN": "bht", + "bhu-Deva-IN": "bhu", + "bhv-Latn-ID": "bhv", + "bhw-Latn-ID": "bhw", + "bhy-Latn-ZZ": "bhy", + "bhz-Latn-ID": "bhz", + "bi-Latn-VU": "bi", + "bia-Latn-AU": "bia", + "bib-Latn-ZZ": "bib", + "bid-Latn-TD": "bid", + "bie-Latn-PG": "bie", + "bif-Latn-GW": "bif", + "big-Latn-ZZ": "big", + "bik-Latn-PH": "bik", + "bil-Latn-NG": "bil", + "bim-Latn-ZZ": "bim", + "bin-Latn-NG": "bin", + "bio-Latn-ZZ": "bio", + "bip-Latn-CD": "bip", + "biq-Latn-ZZ": "biq", + "bir-Latn-PG": "bir", + "bit-Latn-PG": "bit", + "biu-Latn-IN": "biu", + "biv-Latn-GH": "biv", + "biw-Latn-CM": "biw", + "biy-Deva-IN": "biy", + "biz-Latn-CD": "biz", + "bja-Latn-CD": "bja", + "bjb-Latn-AU": "bjb", + "bjc-Latn-PG": "bjc", + "bjf-Syrc-IL": "bjf", + "bjg-Latn-GW": "bjg", + "bjh-Latn-ZZ": "bjh", + "bji-Ethi-ZZ": "bji", + "bjj-Deva-IN": "bjj", + "bjk-Latn-PG": "bjk", + "bjl-Latn-PG": "bjl", + "bjm-Arab-IQ": "bjm", + "bjn-Latn-ID": "bjn", + "bjo-Latn-ZZ": "bjo", + "bjp-Latn-PG": "bjp", + "bjr-Latn-ZZ": "bjr", + "bjs-Latn-BB": "bjs", + "bjt-Latn-SN": "bjt", + "bju-Latn-CM": "bju", + "bjv-Latn-TD": "bjv", + "bjw-Latn-CI": "bjw", + "bjx-Latn-PH": "bjx", + "bjy-Latn-AU": "bjy", + "bjz-Latn-ZZ": "bjz", + "bka-Latn-NG": "bka", + "bkc-Latn-ZZ": "bkc", + "bkd-Latn-PH": "bkd", + "bkf-Latn-CD": "bkf", + "bkg-Latn-CF": "bkg", + "bkh-Latn-CM": "bkh", + "bki-Latn-VU": "bki", + "bkj-Latn-CF": "bkj", + "bkl-Latn-ID": "bkl", + "bkm-Latn-CM": "bkm", + "bkn-Latn-ID": "bkn", + "bko-Latn-CM": "bko", + "bkp-Latn-CD": "bkp", + "bkq-Latn-ZZ": "bkq", + "bkr-Latn-ID": "bkr", + "bks-Latn-PH": "bks", + "bkt-Latn-CD": "bkt", + "bku-Buhd-PH": "bku-Buhd", + "bku-Latn-PH": "bku", + "bkv-Latn-ZZ": "bkv", + "bkw-Latn-CG": "bkw", + "bkx-Latn-TL": "bkx", + "bky-Latn-NG": "bky", + "bkz-Latn-ID": "bkz", + "bla-Latn-CA": "bla", + "blb-Latn-SB": "blb", + "blc-Latn-CA": "blc", + "bld-Latn-ID": "bld", + "ble-Latn-GW": "ble", + "blf-Latn-ID": "blf", + "blh-Latn-LR": "blh", + "bli-Latn-CD": "bli", + "blj-Latn-ID": "blj", + "blk-Mymr-MM": "blk", + "blm-Latn-SS": "blm", + "bln-Latn-PH": "bln", + "blo-Latn-BJ": "blo", + "blp-Latn-SB": "blp", + "blq-Latn-PG": "blq", + "blr-Latn-CN": "blr", + "blr-Tale-CN": "blr-Tale", + "blr-Thai-TH": "blr-Thai", + "bls-Latn-ID": "bls", + "blt-Tavt-VN": "blt", + "blv-Latn-AO": "blv", + "blw-Latn-PH": "blw", + "blx-Latn-PH": "blx", + "bly-Latn-BJ": "bly", + "blz-Latn-ID": "blz", + "bm-Latn-ML": "bm", + "bma-Latn-NG": "bma", + "bmb-Latn-CD": "bmb", + "bmc-Latn-PG": "bmc", + "bmd-Latn-GN": "bmd", + "bme-Latn-CF": "bme", + "bmf-Latn-SL": "bmf", + "bmg-Latn-CD": "bmg", + "bmh-Latn-ZZ": "bmh", + "bmi-Latn-TD": "bmi", + "bmj-Deva-NP": "bmj", + "bmk-Latn-ZZ": "bmk", + "bml-Latn-CD": "bml", + "bmm-Latn-MG": "bmm", + "bmn-Latn-PG": "bmn", + "bmo-Latn-CM": "bmo", + "bmp-Latn-PG": "bmp", + "bmq-Latn-ML": "bmq", + "bmr-Latn-CO": "bmr", + "bms-Latn-NE": "bms", + "bmu-Latn-ZZ": "bmu", + "bmv-Latn-CM": "bmv", + "bmw-Latn-CG": "bmw", + "bmx-Latn-PG": "bmx", + "bmz-Latn-PG": "bmz", + "bn-Beng-BD": "bn", + "bna-Latn-ID": "bna", + "bnb-Latn-MY": "bnb", + "bnc-Latn-PH": "bnc", + "bnd-Latn-ID": "bnd", + "bne-Latn-ID": "bne", + "bnf-Latn-ID": "bnf", + "bng-Latn-ZZ": "bng", + "bni-Latn-CD": "bni", + "bnj-Latn-PH": "bnj", + "bnk-Latn-VU": "bnk", + "bnm-Latn-ZZ": "bnm", + "bnn-Latn-TW": "bnn", + "bno-Latn-PH": "bno", + "bnp-Latn-ZZ": "bnp", + "bnq-Latn-ID": "bnq", + "bnr-Latn-VU": "bnr", + "bns-Deva-IN": "bns", + "bnu-Latn-ID": "bnu", + "bnv-Latn-ID": "bnv", + "bnw-Latn-PG": "bnw", + "bnx-Latn-CD": "bnx", + "bny-Latn-MY": "bny", + "bnz-Latn-CM": "bnz", + "bo-Marc-CN": "bo-Marc", + "bo-Tibt-CN": "bo", + "boa-Latn-PE": "boa", + "bob-Latn-KE": "bob", + "boe-Latn-CM": "boe", + "bof-Latn-BF": "bof", + "boh-Latn-CD": "boh", + "boj-Latn-ZZ": "boj", + "bok-Latn-CG": "bok", + "bol-Latn-NG": "bol", + "bom-Latn-ZZ": "bom", + "bon-Latn-ZZ": "bon", + "boo-Latn-ML": "boo", + "bop-Latn-PG": "bop", + "boq-Latn-PG": "boq", + "bor-Latn-BR": "bor", + "bot-Latn-SS": "bot", + "bou-Latn-TZ": "bou", + "bov-Latn-GH": "bov", + "bow-Latn-PG": "bow", + "box-Latn-BF": "box", + "boy-Latn-CF": "boy", + "boz-Arab-ML": "boz-Arab", + "boz-Latn-ML": "boz", + "bpa-Latn-VU": "bpa", + "bpc-Latn-CM": "bpc", + "bpd-Latn-CF": "bpd", + "bpe-Latn-PG": "bpe", + "bpg-Latn-ID": "bpg", + "bph-Cyrl-RU": "bph", + "bpi-Latn-PG": "bpi", + "bpj-Latn-CD": "bpj", + "bpk-Latn-NC": "bpk", + "bpl-Latn-AU": "bpl", + "bpm-Latn-PG": "bpm", + "bpo-Latn-ID": "bpo", + "bpp-Latn-ID": "bpp", + "bpq-Latn-ID": "bpq", + "bpr-Latn-PH": "bpr", + "bps-Latn-PH": "bps", + "bpt-Latn-AU": "bpt", + "bpu-Latn-PG": "bpu", + "bpv-Latn-ID": "bpv", + "bpw-Latn-PG": "bpw", + "bpx-Deva-IN": "bpx", + "bpy-Beng-IN": "bpy", + "bpz-Latn-ID": "bpz", + "bqa-Latn-BJ": "bqa", + "bqb-Latn-ID": "bqb", + "bqc-Latn-ZZ": "bqc", + "bqd-Latn-CM": "bqd", + "bqf-Arab-GN": "bqf-Arab", + "bqf-Latn-GN": "bqf", + "bqg-Latn-TG": "bqg", + "bqi-Arab-IR": "bqi", + "bqj-Latn-SN": "bqj", + "bqk-Latn-CF": "bqk", + "bql-Latn-PG": "bql", + "bqm-Latn-CM": "bqm", + "bqo-Latn-CM": "bqo", + "bqp-Latn-ZZ": "bqp", + "bqq-Latn-ID": "bqq", + "bqr-Latn-ID": "bqr", + "bqs-Latn-PG": "bqs", + "bqt-Latn-CM": "bqt", + "bqu-Latn-CD": "bqu", + "bqv-Latn-CI": "bqv", + "bqw-Latn-NG": "bqw", + "bqx-Latn-NG": "bqx", + "bqz-Latn-CM": "bqz", + "br-Latn-FR": "br", + "bra-Deva-IN": "bra", + "brb-Khmr-KH": "brb", + "brb-Laoo-LA": "brb-Laoo", + "brb-Latn-VN": "brb-Latn", + "brc-Latn-GY": "brc", + "brd-Deva-NP": "brd", + "brf-Latn-CD": "brf", + "brg-Latn-BO": "brg", + "brh-Arab-PK": "brh", + "bri-Latn-CM": "bri", + "brj-Latn-VU": "brj", + "brk-Arab-SD": "brk", + "brl-Latn-BW": "brl", + "brm-Latn-CD": "brm", + "brn-Latn-CR": "brn", + "brp-Latn-ID": "brp", + "brq-Latn-PG": "brq", + "brr-Latn-SB": "brr", + "brs-Latn-ID": "brs", + "brt-Latn-NG": "brt", + "bru-Laoo-LA": "bru-Laoo", + "bru-Latn-VN": "bru", + "bru-Thai-LA": "bru-Thai", + "brv-Laoo-LA": "brv", + "brx-Deva-IN": "brx", + "bry-Latn-PG": "bry", + "brz-Latn-ZZ": "brz", + "bs-Latn-BA": "bs", + "bsa-Latn-ID": "bsa", + "bsb-Latn-BN": "bsb", + "bsc-Latn-SN": "bsc", + "bse-Latn-CM": "bse", + "bsf-Latn-NG": "bsf", + "bsh-Arab-AF": "bsh", + "bsi-Latn-CM": "bsi", + "bsj-Latn-ZZ": "bsj", + "bsk-Arab-PK": "bsk", + "bsk-Latn-PK": "bsk-Latn", + "bsl-Latn-NG": "bsl", + "bsm-Latn-ID": "bsm", + "bsn-Latn-CO": "bsn", + "bso-Latn-TD": "bso", + "bsp-Latn-GN": "bsp", + "bsq-Bass-LR": "bsq", + "bsr-Latn-NG": "bsr", + "bss-Latn-CM": "bss", + "bst-Ethi-ZZ": "bst", + "bsu-Latn-ID": "bsu", + "bsv-Arab-GN": "bsv-Arab", + "bsv-Latn-GN": "bsv", + "bsw-Ethi-ET": "bsw-Ethi", + "bsw-Latn-ET": "bsw", + "bsx-Latn-NG": "bsx", + "bsy-Latn-MY": "bsy", + "bta-Latn-NG": "bta", + "btc-Latn-CM": "btc", + "btd-Batk-ID": "btd", + "bte-Latn-NG": "bte", + "btf-Latn-TD": "btf", + "btg-Latn-CI": "btg", + "bth-Latn-MY": "bth", + "bti-Latn-ID": "bti", + "btj-Latn-ID": "btj", + "btm-Batk-ID": "btm", + "btn-Latn-PH": "btn", + "bto-Latn-PH": "bto", + "btp-Latn-PG": "btp", + "btq-Latn-MY": "btq", + "btr-Latn-VU": "btr", + "bts-Batk-ID": "bts-Batk", + "bts-Latn-ID": "bts", + "btt-Latn-ZZ": "btt", + "btu-Latn-NG": "btu", + "btv-Deva-PK": "btv", + "btw-Latn-PH": "btw", + "btx-Batk-ID": "btx-Batk", + "btx-Latn-ID": "btx", + "bty-Latn-ID": "bty", + "btz-Latn-ID": "btz", + "bua-Cyrl-RU": "bua", + "bub-Latn-TD": "bub", + "buc-Latn-YT": "buc", + "bud-Latn-ZZ": "bud", + "bue-Latn-CA": "bue", + "buf-Latn-CD": "buf", + "bug-Bugi-ID": "bug-Bugi", + "bug-Latn-ID": "bug", + "buh-Latn-CN": "buh", + "bui-Latn-CG": "bui", + "buj-Latn-NG": "buj", + "buk-Latn-ZZ": "buk", + "bum-Latn-CM": "bum", + "bun-Latn-SL": "bun", + "buo-Latn-ZZ": "buo", + "bup-Latn-ID": "bup", + "buq-Latn-PG": "buq", + "bus-Latn-ZZ": "bus", + "but-Latn-PG": "but", + "buu-Latn-ZZ": "buu", + "buv-Latn-PG": "buv", + "buw-Latn-GA": "buw", + "bux-Latn-NG": "bux", + "buy-Latn-SL": "buy", + "buz-Latn-NG": "buz", + "bva-Latn-TD": "bva", + "bvb-Latn-GQ": "bvb", + "bvc-Latn-SB": "bvc", + "bvd-Latn-SB": "bvd", + "bve-Latn-ID": "bve", + "bvf-Latn-TD": "bvf", + "bvg-Latn-CM": "bvg", + "bvh-Latn-NG": "bvh", + "bvi-Latn-SS": "bvi", + "bvj-Latn-NG": "bvj", + "bvk-Latn-ID": "bvk", + "bvm-Latn-CM": "bvm", + "bvn-Latn-PG": "bvn", + "bvo-Latn-TD": "bvo", + "bvq-Latn-CF": "bvq", + "bvr-Latn-AU": "bvr", + "bvt-Latn-ID": "bvt", + "bvu-Latn-ID": "bvu", + "bvv-Latn-VE": "bvv", + "bvw-Latn-NG": "bvw", + "bvx-Latn-CG": "bvx", + "bvy-Latn-PH": "bvy", + "bvz-Latn-ID": "bvz", + "bwa-Latn-NC": "bwa", + "bwb-Latn-FJ": "bwb", + "bwc-Latn-ZM": "bwc", + "bwd-Latn-ZZ": "bwd", + "bwe-Latn-MM": "bwe-Latn", + "bwe-Mymr-MM": "bwe", + "bwf-Latn-PG": "bwf", + "bwg-Latn-MZ": "bwg", + "bwh-Latn-CM": "bwh", + "bwi-Latn-VE": "bwi", + "bwj-Latn-BF": "bwj", + "bwk-Latn-PG": "bwk", + "bwl-Latn-CD": "bwl", + "bwm-Latn-PG": "bwm", + "bwo-Ethi-ET": "bwo-Ethi", + "bwo-Latn-ET": "bwo", + "bwp-Latn-ID": "bwp", + "bwq-Latn-BF": "bwq", + "bwr-Latn-ZZ": "bwr", + "bws-Latn-CD": "bws", + "bwt-Latn-CM": "bwt", + "bwu-Latn-GH": "bwu", + "bww-Latn-CD": "bww", + "bwx-Latn-CN": "bwx", + "bwy-Latn-BF": "bwy", + "bwz-Latn-CG": "bwz", + "bxa-Latn-SB": "bxa", + "bxb-Latn-SS": "bxb", + "bxc-Latn-GQ": "bxc", + "bxf-Latn-PG": "bxf", + "bxg-Latn-CD": "bxg", + "bxh-Latn-ZZ": "bxh", + "bxi-Latn-AU": "bxi", + "bxj-Latn-AU": "bxj", + "bxl-Latn-BF": "bxl", + "bxm-Cyrl-MN": "bxm", + "bxm-Latn-MN": "bxm-Latn", + "bxm-Mong-MN": "bxm-Mong", + "bxn-Latn-AU": "bxn", + "bxo-Latn-NG": "bxo", + "bxp-Latn-CM": "bxp", + "bxq-Latn-NG": "bxq", + "bxs-Latn-CM": "bxs", + "bxu-Cyrl-CN": "bxu-Cyrl", + "bxu-Latn-CN": "bxu-Latn", + "bxu-Mong-CN": "bxu", + "bxv-Latn-TD": "bxv", + "bxw-Latn-ML": "bxw", + "bxz-Latn-PG": "bxz", + "bya-Latn-PH": "bya", + "byb-Latn-CM": "byb", + "byc-Latn-NG": "byc", + "byd-Latn-ID": "byd", + "bye-Latn-ZZ": "bye", + "byf-Latn-NG": "byf", + "byh-Deva-NP": "byh", + "byi-Latn-CD": "byi", + "byj-Latn-NG": "byj", + "byk-Latn-CN": "byk", + "byl-Latn-ID": "byl", + "bym-Latn-AU": "bym", + "byn-Ethi-ER": "byn", + "byp-Latn-NG": "byp", + "byr-Latn-ZZ": "byr", + "bys-Latn-ZZ": "bys", + "byv-Latn-CM": "byv", + "byw-Deva-NP": "byw", + "byx-Latn-ZZ": "byx", + "byz-Latn-PG": "byz", + "bza-Latn-ZZ": "bza", + "bzb-Latn-ID": "bzb", + "bzc-Latn-MG": "bzc", + "bzd-Latn-CR": "bzd", + "bze-Latn-ML": "bze", + "bzf-Latn-ZZ": "bzf", + "bzh-Latn-ZZ": "bzh", + "bzi-Thai-TH": "bzi", + "bzj-Latn-BZ": "bzj", + "bzk-Latn-NI": "bzk", + "bzl-Latn-ID": "bzl", + "bzm-Latn-CD": "bzm", + "bzn-Latn-ID": "bzn", + "bzo-Latn-CD": "bzo", + "bzp-Latn-ID": "bzp", + "bzq-Latn-ID": "bzq", + "bzr-Latn-AU": "bzr", + "bzt-Latn-001": "bzt", + "bzu-Latn-ID": "bzu", + "bzv-Latn-CM": "bzv", + "bzw-Latn-ZZ": "bzw", + "bzx-Latn-ML": "bzx", + "bzy-Latn-NG": "bzy", + "bzz-Latn-NG": "bzz", + "ca-Latn-AD": "ca-AD", + "ca-Latn-ES": "ca", + "caa-Latn-GT": "caa", + "cab-Latn-HN": "cab", + "cac-Latn-GT": "cac", + "cad-Latn-US": "cad", + "cae-Latn-SN": "cae", + "caf-Cans-CA": "caf-Cans", + "caf-Latn-CA": "caf", + "cag-Latn-PY": "cag", + "cah-Latn-PE": "cah", + "caj-Latn-AR": "caj", + "cak-Latn-GT": "cak", + "cal-Latn-MP": "cal", + "cam-Latn-NC": "cam", + "can-Latn-ZZ": "can", + "cao-Latn-BO": "cao", + "cap-Latn-BO": "cap", + "caq-Latn-IN": "caq", + "car-Latn-VE": "car", + "cas-Latn-BO": "cas", + "cav-Latn-BO": "cav", + "caw-Latn-BO": "caw", + "cax-Latn-BO": "cax", + "cay-Latn-CA": "cay", + "caz-Latn-BO": "caz", + "cbb-Latn-CO": "cbb", + "cbc-Latn-CO": "cbc", + "cbd-Latn-CO": "cbd", + "cbg-Latn-CO": "cbg", + "cbi-Latn-EC": "cbi", + "cbj-Latn-ZZ": "cbj", + "cbk-Brai-PH": "cbk-Brai", + "cbk-Latn-PH": "cbk", + "cbl-Latn-MM": "cbl", + "cbn-Thai-TH": "cbn", + "cbo-Latn-NG": "cbo", + "cbq-Latn-NG": "cbq", + "cbr-Latn-PE": "cbr", + "cbs-Latn-PE": "cbs", + "cbt-Latn-PE": "cbt", + "cbu-Latn-PE": "cbu", + "cbv-Latn-CO": "cbv", + "cbw-Latn-PH": "cbw", + "cby-Latn-CO": "cby", + "ccc-Latn-PE": "ccc", + "ccd-Latn-BR": "ccd", + "cce-Latn-MZ": "cce", + "ccg-Latn-NG": "ccg", + "cch-Latn-NG": "cch", + "ccj-Latn-GW": "ccj", + "ccl-Latn-TZ": "ccl", + "ccm-Latn-MY": "ccm", + "cco-Latn-MX": "cco", + "ccp-Cakm-BD": "ccp", + "ccr-Latn-SV": "ccr", + "cde-Telu-IN": "cde", + "cdf-Beng-IN": "cdf-Beng", + "cdf-Latn-IN": "cdf", + "cdh-Deva-IN": "cdh", + "cdh-Takr-IN": "cdh-Takr", + "cdi-Gujr-IN": "cdi", + "cdj-Deva-IN": "cdj", + "cdm-Deva-NP": "cdm", + "cdm-Latn-NP": "cdm-Latn", + "cdo-Hans-CN": "cdo", + "cdo-Hant-CN": "cdo-Hant", + "cdo-Latn-CN": "cdo-Latn", + "cdr-Latn-NG": "cdr", + "cdz-Beng-IN": "cdz", + "ce-Cyrl-RU": "ce", + "cea-Latn-US": "cea", + "ceb-Latn-PH": "ceb", + "ceg-Latn-PY": "ceg", + "cek-Latn-MM": "cek", + "cen-Latn-NG": "cen", + "cet-Latn-NG": "cet", + "cey-Latn-MM": "cey", + "cfa-Latn-ZZ": "cfa", + "cfd-Latn-NG": "cfd", + "cfg-Latn-NG": "cfg", + "cfm-Beng-IN": "cfm-Beng", + "cfm-Latn-MM": "cfm", + "cga-Latn-PG": "cga", + "cgc-Latn-PH": "cgc", + "cgg-Latn-UG": "cgg", + "cgk-Tibt-BT": "cgk", + "ch-Latn-GU": "ch", + "chb-Latn-CO": "chb", + "chd-Latn-MX": "chd", + "chf-Latn-MX": "chf", + "chg-Arab-TM": "chg", + "chh-Latn-US": "chh", + "chj-Latn-MX": "chj", + "chk-Latn-FM": "chk", + "chl-Latn-US": "chl", + "chm-Cyrl-RU": "chm", + "chn-Dupl-US": "chn-Dupl", + "chn-Latn-US": "chn", + "cho-Latn-US": "cho", + "chp-Latn-CA": "chp", + "chq-Latn-MX": "chq", + "chr-Cher-US": "chr", + "cht-Latn-PE": "cht", + "chw-Latn-MZ": "chw", + "chx-Deva-NP": "chx", + "chy-Latn-US": "chy", + "chz-Latn-MX": "chz", + "cia-Arab-ID": "cia-Arab", + "cia-Hang-ID": "cia-Hang", + "cia-Latn-ID": "cia", + "cib-Latn-BJ": "cib", + "cic-Latn-US": "cic", + "cie-Latn-NG": "cie", + "cih-Deva-IN": "cih", + "cim-Latn-IT": "cim", + "cin-Latn-BR": "cin", + "cip-Latn-MX": "cip", + "cir-Latn-NC": "cir", + "ciw-Cans-US": "ciw-Cans", + "ciw-Latn-US": "ciw", + "ciy-Latn-VE": "ciy", + "cja-Arab-KH": "cja", + "cje-Latn-VN": "cje", + "cjh-Latn-US": "cjh", + "cji-Cyrl-RU": "cji", + "cjk-Latn-AO": "cjk", + "cjm-Cham-VN": "cjm", + "cjn-Latn-PG": "cjn", + "cjo-Latn-PE": "cjo", + "cjp-Latn-CR": "cjp", + "cjs-Cyrl-RU": "cjs-Cyrl", + "cjs-Latn-RU": "cjs", + "cjv-Latn-ZZ": "cjv", + "cjy-Hans-CN": "cjy", + "cjy-Hant-CN": "cjy-Hant", + "ckb-Arab-IQ": "ckb", + "ckl-Latn-ZZ": "ckl", + "ckm-Glag-HR": "ckm-Glag", + "ckm-Latn-HR": "ckm", + "ckn-Latn-MM": "ckn", + "cko-Latn-ZZ": "cko", + "ckq-Latn-TD": "ckq", + "ckr-Latn-PG": "ckr", + "cks-Latn-NC": "cks", + "ckt-Cyrl-RU": "ckt", + "cku-Latn-US": "cku", + "ckv-Latn-TW": "ckv", + "ckx-Latn-CM": "ckx", + "cky-Latn-ZZ": "cky", + "ckz-Latn-GT": "ckz", + "cla-Latn-ZZ": "cla", + "clc-Latn-CA": "clc", + "cle-Latn-MX": "cle", + "clh-Arab-PK": "clh", + "cli-Latn-GH": "cli", + "clj-Latn-MM": "clj", + "clk-Latn-IN": "clk", + "clk-Tibt-CN": "clk-Tibt", + "cll-Latn-GH": "cll", + "clm-Latn-US": "clm", + "clo-Latn-MX": "clo", + "clt-Latn-MM": "clt", + "clu-Latn-PH": "clu", + "clw-Cyrl-RU": "clw", + "cly-Latn-MX": "cly", + "cma-Latn-VN": "cma", + "cme-Latn-ZZ": "cme", + "cmg-Soyo-MN": "cmg", + "cmg-Zanb-MN": "cmg-Zanb", + "cmi-Latn-CO": "cmi", + "cml-Latn-ID": "cml", + "cmo-Khmr-KH": "cmo-Khmr", + "cmo-Latn-KH": "cmo-KH", + "cmo-Latn-VN": "cmo", + "cmr-Latn-MM": "cmr", + "cms-Latn-IT": "cms", + "cmt-Latn-ZA": "cmt", + "cna-Tibt-IN": "cna", + "cnb-Latn-MM": "cnb", + "cnc-Latn-VN": "cnc", + "cng-Latn-CN": "cng", + "cnh-Latn-MM": "cnh", + "cni-Latn-PE": "cni", + "cnk-Latn-MM": "cnk", + "cnl-Latn-MX": "cnl", + "cnp-Hans-CN": "cnp", + "cnp-Hant-CN": "cnp-Hant", + "cnq-Latn-CM": "cnq", + "cns-Latn-ID": "cns", + "cnt-Latn-MX": "cnt", + "cnw-Latn-MM": "cnw", + "cnx-Latn-GB": "cnx", + "co-Latn-FR": "co", + "coa-Latn-AU": "coa", + "cob-Latn-MX": "cob", + "coc-Latn-MX": "coc", + "cod-Latn-PE": "cod", + "coe-Latn-CO": "coe", + "cof-Latn-EC": "cof", + "cog-Thai-TH": "cog", + "coh-Latn-KE": "coh", + "coj-Latn-MX": "coj", + "cok-Latn-MX": "cok", + "col-Latn-US": "col", + "com-Latn-US": "com", + "coo-Latn-CA": "coo", + "cop-Copt-EG": "cop", + "coq-Latn-US": "coq", + "cot-Latn-PE": "cot", + "cou-Latn-SN": "cou", + "cox-Latn-PE": "cox", + "coz-Latn-MX": "coz", + "cpa-Latn-MX": "cpa", + "cpb-Latn-PE": "cpb", + "cpc-Latn-PE": "cpc", + "cpg-Grek-GR": "cpg", + "cpi-Latn-NR": "cpi", + "cpn-Latn-GH": "cpn", + "cpo-Latn-BF": "cpo", + "cps-Latn-PH": "cps", + "cpu-Latn-PE": "cpu", + "cpx-Latn-CN": "cpx", + "cpy-Latn-PE": "cpy", + "cqd-Latn-CN": "cqd", + "cr-Cans-CA": "cr", + "crb-Latn-VC": "crb", + "crc-Latn-VU": "crc", + "crd-Latn-US": "crd", + "crf-Latn-CO": "crf", + "crg-Latn-CA": "crg", + "crh-Cyrl-UA": "crh", + "cri-Latn-ST": "cri", + "crj-Cans-CA": "crj", + "crj-Latn-CA": "crj-Latn", + "crk-Cans-CA": "crk", + "crl-Cans-CA": "crl", + "crm-Cans-CA": "crm", + "crn-Latn-MX": "crn", + "cro-Latn-US": "cro", + "crq-Latn-AR": "crq", + "crs-Latn-SC": "crs", + "crt-Latn-AR": "crt", + "crv-Latn-IN": "crv", + "crw-Latn-VN": "crw", + "crx-Cans-CA": "crx-Cans", + "crx-Latn-CA": "crx", + "cry-Latn-NG": "cry", + "crz-Latn-US": "crz", + "cs-Latn-CZ": "cs", + "csa-Latn-MX": "csa", + "csb-Latn-PL": "csb", + "csh-Latn-MM": "csh-Latn", + "csh-Mymr-MM": "csh", + "csj-Latn-MM": "csj", + "csk-Latn-SN": "csk", + "csm-Latn-US": "csm", + "cso-Latn-MX": "cso", + "csp-Hans-CN": "csp", + "csp-Hant-CN": "csp-Hant", + "css-Latn-US": "css", + "cst-Latn-US": "cst", + "csv-Latn-MM": "csv", + "csw-Cans-CA": "csw", + "csy-Latn-MM": "csy", + "csz-Latn-US": "csz", + "cta-Latn-MX": "cta", + "ctc-Latn-US": "ctc", + "ctd-Pauc-MM": "ctd", + "cte-Latn-MX": "cte", + "ctg-Arab-BD": "ctg-Arab", + "ctg-Beng-BD": "ctg", + "ctg-Latn-BD": "ctg-Latn", + "cth-Latn-MM": "cth", + "ctl-Latn-MX": "ctl", + "ctm-Latn-US": "ctm", + "ctn-Deva-NP": "ctn", + "cto-Latn-CO": "cto", + "ctp-Latn-MX": "ctp", + "cts-Latn-PH": "cts", + "ctt-Taml-IN": "ctt", + "ctu-Latn-MX": "ctu", + "ctz-Latn-MX": "ctz", + "cu-Cyrl-RU": "cu", + "cu-Glag-BG": "cu-Glag", + "cua-Latn-VN": "cua", + "cub-Latn-CO": "cub", + "cuc-Latn-MX": "cuc", + "cuh-Latn-KE": "cuh", + "cui-Latn-CO": "cui", + "cuj-Latn-PE": "cuj", + "cuk-Latn-PA": "cuk", + "cul-Latn-BR": "cul", + "cuo-Latn-VE": "cuo", + "cup-Latn-US": "cup", + "cut-Latn-MX": "cut", + "cuu-Lana-CN": "cuu", + "cuv-Latn-CM": "cuv", + "cux-Latn-MX": "cux", + "cv-Cyrl-RU": "cv", + "cvg-Latn-IN": "cvg", + "cvg-Tibt-IN": "cvg-Tibt", + "cvn-Latn-MX": "cvn", + "cwa-Latn-TZ": "cwa", + "cwb-Latn-MZ": "cwb", + "cwe-Latn-TZ": "cwe", + "cwg-Latn-MY": "cwg", + "cwt-Latn-SN": "cwt", + "cy-Latn-GB": "cy", + "cya-Latn-MX": "cya", + "cyb-Latn-BO": "cyb", + "cyo-Latn-PH": "cyo", + "czh-Hans-CN": "czh", + "czh-Hant-CN": "czh-Hant", + "czk-Hebr-CZ": "czk", + "czn-Latn-MX": "czn", + "czt-Latn-MM": "czt", + "da-Latn-DK": "da", + "daa-Latn-TD": "daa", + "dac-Latn-PG": "dac", + "dad-Latn-ZZ": "dad", + "dae-Latn-CM": "dae", + "dag-Latn-ZZ": "dag", + "dah-Latn-ZZ": "dah", + "dai-Latn-TD": "dai", + "daj-Latn-SD": "daj", + "dak-Latn-US": "dak", + "dal-Latn-KE": "dal", + "dam-Latn-NG": "dam", + "dao-Latn-MM": "dao", + "daq-Deva-IN": "daq", + "dar-Cyrl-RU": "dar", + "das-Latn-CI": "das", + "dau-Latn-TD": "dau", + "dav-Latn-KE": "dav", + "daw-Latn-PH": "daw", + "dax-Latn-AU": "dax", + "daz-Latn-ID": "daz", + "dba-Latn-ML": "dba", + "dbb-Latn-NG": "dbb", + "dbd-Latn-ZZ": "dbd", + "dbe-Latn-ID": "dbe", + "dbf-Latn-ID": "dbf", + "dbg-Latn-ML": "dbg", + "dbi-Latn-NG": "dbi", + "dbj-Arab-MY": "dbj-Arab", + "dbj-Latn-MY": "dbj", + "dbl-Latn-AU": "dbl", + "dbm-Latn-NG": "dbm", + "dbn-Latn-ID": "dbn", + "dbo-Latn-NG": "dbo", + "dbp-Latn-NG": "dbp", + "dbq-Latn-ZZ": "dbq", + "dbt-Latn-ML": "dbt", + "dbu-Latn-ML": "dbu", + "dbv-Latn-NG": "dbv", + "dbw-Latn-ML": "dbw", + "dby-Latn-PG": "dby", + "dcc-Arab-IN": "dcc", + "dcr-Latn-VI": "dcr", + "dda-Latn-AU": "dda", + "ddd-Latn-SS": "ddd", + "dde-Latn-CG": "dde", + "ddg-Latn-TL": "ddg", + "ddi-Latn-PG": "ddi", + "ddj-Latn-AU": "ddj", + "ddn-Latn-ZZ": "ddn", + "ddo-Cyrl-RU": "ddo", + "ddr-Latn-AU": "ddr", + "dds-Latn-ML": "dds", + "ddw-Latn-ID": "ddw", + "de-Latn-AT": "de-AT", + "de-Latn-CH": "de-CH", + "de-Latn-DE": "de", + "de-Latn-EZ": "de-EZ", + "de-Latn-LI": "de-LI", + "dec-Latn-SD": "dec", + "ded-Latn-ZZ": "ded", + "dee-Latn-LR": "dee", + "def-Arab-IR": "def", + "deg-Latn-NG": "deg", + "deh-Arab-PK": "deh", + "dei-Latn-ID": "dei", + "dek-Latn-CM": "dek", + "del-Latn-US": "del", + "dem-Latn-ID": "dem", + "den-Latn-CA": "den", + "deq-Latn-CF": "deq", + "der-Beng-IN": "der", + "der-Latn-IN": "der-Latn", + "des-Latn-BR": "des", + "dev-Latn-PG": "dev", + "dez-Latn-CD": "dez", + "dga-Latn-ZZ": "dga", + "dgb-Latn-ML": "dgb", + "dgc-Latn-PH": "dgc", + "dgd-Latn-BF": "dgd", + "dge-Latn-PG": "dge", + "dgg-Latn-PG": "dgg", + "dgh-Latn-ZZ": "dgh", + "dgi-Latn-ZZ": "dgi", + "dgk-Latn-CF": "dgk", + "dgl-Arab-ZZ": "dgl", + "dgn-Latn-AU": "dgn", + "dgr-Latn-CA": "dgr", + "dgs-Latn-BF": "dgs", + "dgt-Latn-AU": "dgt", + "dgw-Latn-AU": "dgw", + "dgx-Latn-PG": "dgx", + "dgz-Latn-ZZ": "dgz", + "dhg-Latn-AU": "dhg", + "dhi-Deva-NP": "dhi", + "dhl-Latn-AU": "dhl", + "dhm-Latn-AO": "dhm", + "dhn-Gujr-IN": "dhn", + "dho-Deva-IN": "dho", + "dhr-Latn-AU": "dhr", + "dhs-Latn-TZ": "dhs", + "dhu-Latn-AU": "dhu", + "dhv-Latn-NC": "dhv", + "dhw-Deva-NP": "dhw", + "dhx-Latn-AU": "dhx", + "dia-Latn-ZZ": "dia", + "dib-Latn-SS": "dib", + "dic-Latn-CI": "dic", + "did-Latn-SS": "did", + "dif-Latn-AU": "dif", + "dig-Latn-KE": "dig", + "dih-Latn-MX": "dih", + "dii-Latn-CM": "dii", + "dij-Latn-ID": "dij", + "dil-Latn-SD": "dil", + "din-Arab-SS": "din-Arab", + "din-Latn-SS": "din", + "dio-Latn-NG": "dio", + "dip-Latn-SS": "dip", + "dir-Latn-NG": "dir", + "dis-Beng-IN": "dis-Beng", + "dis-Latn-IN": "dis", + "diu-Latn-NA": "diu", + "diw-Latn-SS": "diw", + "dix-Latn-VU": "dix", + "diy-Latn-ID": "diy", + "diz-Latn-CD": "diz", + "dja-Latn-AU": "dja", + "djb-Latn-AU": "djb", + "djc-Latn-TD": "djc", + "djd-Latn-AU": "djd", + "dje-Latn-NE": "dje", + "djf-Latn-AU": "djf", + "dji-Latn-AU": "dji", + "djj-Latn-AU": "djj", + "djk-Latn-SR": "djk", + "djm-Latn-ML": "djm", + "djn-Latn-AU": "djn", + "djo-Latn-ID": "djo", + "djr-Latn-AU": "djr", + "dju-Latn-PG": "dju", + "djw-Latn-AU": "djw", + "dka-Tibt-BT": "dka", + "dkg-Latn-NG": "dkg", + "dkk-Latn-ID": "dkk", + "dkr-Latn-MY": "dkr", + "dks-Latn-SS": "dks", + "dkx-Latn-CM": "dkx", + "dlg-Cyrl-RU": "dlg", + "dlm-Latn-HR": "dlm", + "dln-Latn-IN": "dln", + "dma-Latn-GA": "dma", + "dmb-Latn-ML": "dmb", + "dmc-Latn-PG": "dmc", + "dmd-Latn-AU": "dmd", + "dme-Latn-CM": "dme", + "dmf-Medf-NG": "dmf", + "dmg-Latn-MY": "dmg", + "dmk-Arab-PK": "dmk", + "dml-Arab-PK": "dml", + "dmm-Latn-CM": "dmm", + "dmo-Latn-CM": "dmo", + "dmr-Latn-ID": "dmr", + "dms-Latn-ID": "dms", + "dmu-Latn-ID": "dmu", + "dmv-Latn-MY": "dmv", + "dmw-Latn-AU": "dmw", + "dmx-Latn-MZ": "dmx", + "dmy-Latn-ID": "dmy", + "dna-Latn-ID": "dna", + "dnd-Latn-PG": "dnd", + "dne-Latn-TZ": "dne", + "dng-Arab-KG": "dng-Arab", + "dng-Cyrl-KG": "dng", + "dni-Latn-ID": "dni", + "dnj-Latn-CI": "dnj", + "dnk-Latn-ID": "dnk", + "dnn-Latn-BF": "dnn", + "dno-Latn-CD": "dno", + "dnr-Latn-PG": "dnr", + "dnt-Latn-ID": "dnt", + "dnu-Mymr-MM": "dnu", + "dnv-Mymr-MM": "dnv", + "dnw-Latn-ID": "dnw", + "dny-Latn-BR": "dny", + "doa-Latn-PG": "doa", + "dob-Latn-ZZ": "dob", + "doc-Latn-CN": "doc", + "doe-Latn-TZ": "doe", + "dof-Latn-PG": "dof", + "doh-Latn-NG": "doh", + "doi-Deva-IN": "doi", + "doi-Dogr-IN": "doi-Dogr", + "doi-Takr-IN": "doi-Takr", + "dok-Latn-ID": "dok", + "dol-Latn-PG": "dol", + "don-Latn-PG": "don", + "doo-Latn-CD": "doo", + "dop-Latn-ZZ": "dop", + "dor-Latn-SB": "dor", + "dos-Latn-BF": "dos", + "dot-Latn-NG": "dot", + "dov-Latn-ZW": "dov", + "dow-Latn-ZZ": "dow", + "dox-Ethi-ET": "dox", + "doy-Latn-GH": "doy", + "dpp-Latn-MY": "dpp", + "drc-Latn-PT": "drc", + "dre-Tibt-NP": "dre", + "drg-Latn-MY": "drg", + "dri-Latn-ZZ": "dri", + "drl-Latn-AU": "drl", + "drn-Latn-ID": "drn", + "dro-Latn-MY": "dro", + "drq-Deva-NP": "drq", + "drs-Ethi-ZZ": "drs", + "drt-Latn-NL": "drt", + "dru-Latn-TW": "dru", + "dry-Deva-NP": "dry", + "dsb-Latn-DE": "dsb", + "dsh-Latn-KE": "dsh", + "dsi-Latn-TD": "dsi", + "dsn-Latn-ID": "dsn", + "dso-Orya-IN": "dso", + "dsq-Arab-ML": "dsq-Arab", + "dsq-Latn-ML": "dsq", + "dta-Cyrl-CN": "dta-Cyrl", + "dta-Hans-CN": "dta-Hans", + "dta-Latn-CN": "dta", + "dtb-Latn-MY": "dtb", + "dtd-Latn-CA": "dtd", + "dth-Latn-AU": "dth", + "dti-Latn-ML": "dti", + "dtk-Latn-ML": "dtk", + "dtm-Latn-ML": "dtm", + "dto-Latn-ML": "dto", + "dtp-Latn-MY": "dtp", + "dtr-Latn-MY": "dtr", + "dts-Latn-ZZ": "dts", + "dtt-Latn-ML": "dtt", + "dtu-Latn-ML": "dtu", + "dty-Deva-NP": "dty", + "dua-Latn-CM": "dua", + "dub-Gujr-IN": "dub", + "duc-Latn-ZZ": "duc", + "due-Latn-PH": "due", + "duf-Latn-NC": "duf", + "dug-Latn-ZZ": "dug", + "duh-Deva-IN": "duh", + "duh-Gujr-IN": "duh-Gujr", + "dui-Latn-PG": "dui", + "duk-Latn-PG": "duk", + "dul-Latn-PH": "dul", + "dum-Latn-NL": "dum", + "dun-Latn-ID": "dun", + "duo-Latn-PH": "duo", + "dup-Latn-ID": "dup", + "duq-Latn-ID": "duq", + "dur-Latn-CM": "dur", + "dus-Deva-NP": "dus", + "duu-Latn-CN": "duu", + "duv-Latn-ID": "duv", + "duw-Latn-ID": "duw", + "dux-Latn-ML": "dux", + "duy-Latn-PH": "duy", + "duz-Latn-CM": "duz", + "dv-Diak-MV": "dv-Diak", + "dv-Thaa-MV": "dv", + "dva-Latn-ZZ": "dva", + "dwa-Latn-NG": "dwa", + "dwk-Orya-IN": "dwk", + "dwr-Ethi-ET": "dwr-Ethi", + "dwr-Latn-ET": "dwr", + "dws-Latn-001": "dws", + "dwu-Latn-AU": "dwu", + "dww-Latn-ZZ": "dww", + "dwy-Latn-AU": "dwy", + "dwz-Deva-NP": "dwz", + "dya-Latn-BF": "dya", + "dyb-Latn-AU": "dyb", + "dyd-Latn-AU": "dyd", + "dyg-Latn-PH": "dyg", + "dyi-Latn-CI": "dyi", + "dym-Latn-ML": "dym", + "dyn-Latn-AU": "dyn", + "dyo-Latn-SN": "dyo", + "dyu-Latn-BF": "dyu", + "dyy-Latn-AU": "dyy", + "dz-Tibt-BT": "dz", + "dza-Latn-NG": "dza", + "dze-Latn-AU": "dze", + "dzg-Latn-ZZ": "dzg", + "dzl-Tibt-BT": "dzl", + "dzn-Latn-CD": "dzn", + "eaa-Latn-AU": "eaa", + "ebc-Latn-ID": "ebc", + "ebg-Latn-NG": "ebg", + "ebk-Latn-PH": "ebk", + "ebo-Latn-CG": "ebo", + "ebr-Latn-CI": "ebr", + "ebu-Latn-KE": "ebu", + "ecr-Grek-GR": "ecr", + "ecy-Cprt-CY": "ecy", + "ee-Latn-GH": "ee", + "efa-Latn-NG": "efa", + "efe-Latn-CD": "efe", + "efi-Latn-NG": "efi", + "ega-Latn-CI": "ega", + "egl-Latn-IT": "egl", + "egm-Latn-TZ": "egm", + "ego-Latn-NG": "ego", + "egy-Egyp-EG": "egy", + "ehu-Latn-NG": "ehu", + "eip-Latn-ID": "eip", + "eit-Latn-PG": "eit", + "eiv-Latn-PG": "eiv", + "eja-Latn-GW": "eja", + "eka-Latn-ZZ": "eka", + "eke-Latn-NG": "eke", + "ekg-Latn-ID": "ekg", + "eki-Latn-NG": "eki", + "ekl-Latn-BD": "ekl", + "ekm-Latn-CM": "ekm", + "eko-Arab-MZ": "eko-Arab", + "eko-Latn-MZ": "eko", + "ekp-Latn-NG": "ekp", + "ekr-Latn-NG": "ekr", + "eky-Kali-MM": "eky", + "el-Grek-CY": "el-CY", + "el-Grek-GR": "el", + "ele-Latn-PG": "ele", + "elk-Latn-PG": "elk", + "elm-Latn-NG": "elm", + "elo-Latn-KE": "elo", + "elu-Latn-PG": "elu", + "ema-Latn-ZZ": "ema", + "emb-Latn-ID": "emb", + "eme-Latn-GF": "eme", + "emg-Deva-NP": "emg", + "emi-Latn-ZZ": "emi", + "emm-Latn-MX": "emm", + "emn-Latn-CM": "emn", + "emp-Latn-PA": "emp", + "ems-Cyrl-US": "ems-Cyrl", + "ems-Latn-US": "ems", + "emu-Deva-IN": "emu", + "emw-Latn-ID": "emw", + "emx-Latn-FR": "emx", + "emz-Latn-CM": "emz", + "en-Latn-AU": "en-AU", + "en-Latn-DG": "en-DG", + "en-Latn-ET": "en-ET", + "en-Latn-GB": "en-GB", + "en-Latn-GU": "en-GU", + "en-Latn-IE": "en-IE", + "en-Latn-NG": "en-NG", + "en-Latn-PG": "en-PG", + "en-Latn-US": "en", + "en-Latn-ZA": "en-ZA", + "en-Shaw-GB": "en-Shaw", + "ena-Latn-PG": "ena", + "enb-Latn-KE": "enb", + "enc-Latn-VN": "enc", + "end-Latn-ID": "end", + "enf-Cyrl-RU": "enf", + "enh-Cyrl-RU": "enh", + "enl-Latn-PY": "enl", + "enm-Latn-GB": "enm", + "enn-Latn-ZZ": "enn", + "eno-Latn-ID": "eno", + "enq-Latn-ZZ": "enq", + "enr-Latn-ID": "enr", + "env-Latn-NG": "env", + "enw-Latn-NG": "enw", + "enx-Latn-PY": "enx", + "eo-Latn-001": "eo", + "eot-Latn-CI": "eot", + "epi-Latn-NG": "epi", + "era-Taml-IN": "era", + "erg-Latn-VU": "erg", + "erh-Latn-NG": "erh", + "eri-Latn-ZZ": "eri", + "erk-Latn-VU": "erk", + "err-Latn-AU": "err", + "ert-Latn-ID": "ert", + "erw-Latn-ID": "erw", + "es-Latn-419": "es-419", + "es-Latn-AR": "es-AR", + "es-Latn-BO": "es-BO", + "es-Latn-CL": "es-CL", + "es-Latn-CO": "es-CO", + "es-Latn-CR": "es-CR", + "es-Latn-CU": "es-CU", + "es-Latn-DO": "es-DO", + "es-Latn-EA": "es-EA", + "es-Latn-EC": "es-EC", + "es-Latn-ES": "es", + "es-Latn-GQ": "es-GQ", + "es-Latn-GT": "es-GT", + "es-Latn-HN": "es-HN", + "es-Latn-IC": "es-IC", + "es-Latn-MX": "es-MX", + "es-Latn-NI": "es-NI", + "es-Latn-PA": "es-PA", + "es-Latn-PE": "es-PE", + "es-Latn-PR": "es-PR", + "es-Latn-SV": "es-SV", + "es-Latn-UY": "es-UY", + "es-Latn-VE": "es-VE", + "ese-Latn-BO": "ese", + "esg-Gonm-IN": "esg", + "esh-Arab-IR": "esh", + "esi-Latn-US": "esi", + "esm-Latn-CI": "esm", + "ess-Cyrl-US": "ess-Cyrl", + "ess-Latn-US": "ess", + "esu-Latn-US": "esu", + "esy-Latn-PH": "esy", + "et-Latn-EE": "et", + "etb-Latn-NG": "etb", + "etn-Latn-VU": "etn", + "eto-Latn-CM": "eto", + "etr-Latn-ZZ": "etr", + "ets-Latn-NG": "ets", + "ett-Ital-IT": "ett", + "etu-Latn-ZZ": "etu", + "etx-Latn-ZZ": "etx", + "etz-Latn-ID": "etz", + "eu-Latn-ES": "eu", + "eve-Cyrl-RU": "eve", + "evh-Latn-NG": "evh", + "evn-Cyrl-RU": "evn", + "evn-Latn-CN": "evn-Latn", + "evn-Mong-CN": "evn-Mong", + "ewo-Latn-CM": "ewo", + "ext-Latn-ES": "ext", + "eya-Latn-US": "eya", + "eyo-Latn-KE": "eyo", + "eza-Latn-ZZ": "eza", + "eze-Latn-NG": "eze", + "fa-Arab-AF": "fa-AF", + "fa-Arab-IR": "fa", + "fa-Arab-TJ": "fa-TJ", + "faa-Latn-ZZ": "faa", + "fab-Latn-ZZ": "fab", + "fad-Latn-PG": "fad", + "faf-Latn-SB": "faf", + "fag-Latn-ZZ": "fag", + "fah-Latn-NG": "fah", + "fai-Latn-ZZ": "fai", + "faj-Latn-PG": "faj", + "fak-Latn-CM": "fak", + "fal-Latn-CM": "fal", + "fam-Latn-NG": "fam", + "fan-Latn-GQ": "fan", + "fap-Latn-SN": "fap", + "far-Latn-SB": "far", + "fau-Latn-ID": "fau", + "fax-Latn-ES": "fax", + "fay-Arab-IR": "fay", + "faz-Arab-IR": "faz", + "fbl-Latn-PH": "fbl", + "fer-Latn-SS": "fer", + "ff-Adlm-GN": "ff-Adlm", + "ff-Latn-SN": "ff", + "ffi-Latn-ZZ": "ffi", + "ffm-Latn-ML": "ffm", + "fgr-Latn-TD": "fgr", + "fi-Latn-FI": "fi", + "fia-Arab-SD": "fia", + "fie-Latn-NG": "fie", + "fif-Latn-SA": "fif", + "fil-Latn-PH": "fil", + "fil-Tglg-PH": "fil-Tglg", + "fip-Latn-TZ": "fip", + "fir-Latn-NG": "fir", + "fit-Latn-SE": "fit", + "fiw-Latn-PG": "fiw", + "fj-Latn-FJ": "fj", + "fkk-Latn-NG": "fkk", + "fkv-Latn-NO": "fkv", + "fla-Latn-US": "fla", + "flh-Latn-ID": "flh", + "fli-Latn-NG": "fli", + "fll-Latn-CM": "fll", + "fln-Latn-AU": "fln", + "flr-Latn-ZZ": "flr", + "fly-Latn-ZA": "fly", + "fmp-Latn-ZZ": "fmp", + "fmu-Deva-IN": "fmu", + "fnb-Latn-VU": "fnb", + "fng-Latn-ZA": "fng", + "fni-Latn-TD": "fni", + "fo-Latn-FO": "fo", + "fod-Latn-ZZ": "fod", + "foi-Latn-PG": "foi", + "fom-Latn-CD": "fom", + "fon-Latn-BJ": "fon", + "for-Latn-ZZ": "for", + "fos-Latn-TW": "fos", + "fpe-Latn-ZZ": "fpe", + "fqs-Latn-ZZ": "fqs", + "fr-Brai-FR": "fr-Brai", + "fr-Dupl-FR": "fr-Dupl", + "fr-Latn-BF": "fr-BF", + "fr-Latn-BJ": "fr-BJ", + "fr-Latn-BL": "fr-BL", + "fr-Latn-CF": "fr-CF", + "fr-Latn-CG": "fr-CG", + "fr-Latn-CI": "fr-CI", + "fr-Latn-CM": "fr-CM", + "fr-Latn-DZ": "fr-DZ", + "fr-Latn-FR": "fr", + "fr-Latn-GA": "fr-GA", + "fr-Latn-GF": "fr-GF", + "fr-Latn-GN": "fr-GN", + "fr-Latn-GP": "fr-GP", + "fr-Latn-KM": "fr-KM", + "fr-Latn-LU": "fr-LU", + "fr-Latn-MA": "fr-MA", + "fr-Latn-MC": "fr-MC", + "fr-Latn-MF": "fr-MF", + "fr-Latn-MQ": "fr-MQ", + "fr-Latn-MR": "fr-MR", + "fr-Latn-NC": "fr-NC", + "fr-Latn-PF": "fr-PF", + "fr-Latn-PM": "fr-PM", + "fr-Latn-RE": "fr-RE", + "fr-Latn-SC": "fr-SC", + "fr-Latn-SN": "fr-SN", + "fr-Latn-SY": "fr-SY", + "fr-Latn-TD": "fr-TD", + "fr-Latn-TF": "fr-TF", + "fr-Latn-TG": "fr-TG", + "fr-Latn-TN": "fr-TN", + "fr-Latn-WF": "fr-WF", + "fr-Latn-YT": "fr-YT", + "frc-Latn-US": "frc", + "frd-Latn-ID": "frd", + "frk-Latn-DE": "frk", + "frm-Latn-FR": "frm", + "fro-Latn-FR": "fro", + "frp-Latn-FR": "frp", + "frq-Latn-PG": "frq", + "frr-Latn-DE": "frr", + "frs-Latn-DE": "frs", + "frt-Latn-VU": "frt", + "fub-Arab-CM": "fub", + "fud-Latn-WF": "fud", + "fue-Latn-ZZ": "fue", + "fuf-Latn-GN": "fuf", + "fuh-Latn-ZZ": "fuh", + "fui-Latn-TD": "fui", + "fum-Latn-NG": "fum", + "fun-Latn-BR": "fun", + "fuq-Latn-NE": "fuq", + "fur-Latn-IT": "fur", + "fut-Latn-VU": "fut", + "fuu-Latn-CD": "fuu", + "fuv-Latn-NG": "fuv", + "fuy-Latn-ZZ": "fuy", + "fvr-Latn-SD": "fvr", + "fwa-Latn-NC": "fwa", + "fwe-Latn-NA": "fwe", + "fy-Latn-NL": "fy", + "ga-Latn-IE": "ga", + "gaa-Latn-GH": "gaa", + "gab-Latn-TD": "gab", + "gac-Deva-IN": "gac-Deva", + "gac-Latn-IN": "gac", + "gad-Latn-PH": "gad", + "gae-Latn-VE": "gae", + "gaf-Latn-ZZ": "gaf", + "gag-Latn-MD": "gag", + "gah-Latn-ZZ": "gah", + "gai-Latn-PG": "gai", + "gaj-Latn-ZZ": "gaj", + "gak-Latn-ID": "gak", + "gal-Latn-TL": "gal", + "gam-Latn-ZZ": "gam", + "gan-Hans-CN": "gan", + "gao-Latn-PG": "gao", + "gap-Latn-PG": "gap", + "gaq-Orya-IN": "gaq", + "gar-Latn-PG": "gar", + "gas-Gujr-IN": "gas", + "gat-Latn-PG": "gat", + "gau-Telu-IN": "gau", + "gaw-Latn-ZZ": "gaw", + "gax-Ethi-ET": "gax-Ethi", + "gax-Latn-ET": "gax", + "gay-Latn-ID": "gay", + "gba-Latn-ZZ": "gba", + "gbb-Latn-AU": "gbb", + "gbd-Latn-AU": "gbd", + "gbe-Latn-PG": "gbe", + "gbf-Latn-ZZ": "gbf", + "gbg-Latn-CF": "gbg", + "gbh-Latn-BJ": "gbh", + "gbi-Latn-ID": "gbi", + "gbj-Orya-IN": "gbj", + "gbk-Deva-IN": "gbk", + "gbk-Takr-IN": "gbk-Takr", + "gbl-Deva-IN": "gbl-Deva", + "gbl-Gujr-IN": "gbl", + "gbm-Deva-IN": "gbm", + "gbn-Latn-SS": "gbn", + "gbp-Latn-CF": "gbp", + "gbq-Latn-CF": "gbq", + "gbr-Latn-NG": "gbr", + "gbs-Latn-BJ": "gbs", + "gbu-Latn-AU": "gbu", + "gbv-Latn-CF": "gbv", + "gbw-Latn-AU": "gbw", + "gbx-Latn-BJ": "gbx", + "gby-Latn-ZZ": "gby", + "gbz-Arab-IR": "gbz", + "gcc-Latn-PG": "gcc", + "gcd-Latn-AU": "gcd", + "gcf-Latn-GP": "gcf", + "gcl-Latn-GD": "gcl", + "gcn-Latn-PG": "gcn", + "gcr-Latn-GF": "gcr", + "gct-Latn-VE": "gct", + "gd-Latn-GB": "gd", + "gdb-Orya-IN": "gdb", + "gdb-Telu-IN": "gdb-Telu", + "gdc-Latn-AU": "gdc", + "gdd-Latn-PG": "gdd", + "gde-Latn-ZZ": "gde", + "gdf-Latn-NG": "gdf", + "gdg-Latn-PH": "gdg", + "gdh-Latn-AU": "gdh", + "gdi-Latn-CF": "gdi", + "gdj-Latn-AU": "gdj", + "gdk-Latn-TD": "gdk", + "gdl-Ethi-ET": "gdl-Ethi", + "gdl-Latn-ET": "gdl", + "gdm-Latn-TD": "gdm", + "gdn-Latn-ZZ": "gdn", + "gdo-Cyrl-RU": "gdo", + "gdq-Latn-YE": "gdq", + "gdr-Latn-ZZ": "gdr", + "gdt-Latn-AU": "gdt", + "gdu-Latn-NG": "gdu", + "gdx-Deva-IN": "gdx", + "gea-Latn-NG": "gea", + "geb-Latn-ZZ": "geb", + "gec-Latn-LR": "gec", + "ged-Latn-NG": "ged", + "gef-Latn-ID": "gef", + "geg-Latn-NG": "geg", + "geh-Latn-CA": "geh", + "gei-Latn-ID": "gei", + "gej-Latn-ZZ": "gej", + "gek-Latn-NG": "gek", + "gel-Latn-ZZ": "gel", + "geq-Latn-CF": "geq", + "ges-Latn-ID": "ges", + "gev-Latn-GA": "gev", + "gew-Latn-NG": "gew", + "gex-Latn-SO": "gex", + "gey-Latn-CD": "gey", + "gez-Ethi-ET": "gez", + "gfk-Latn-ZZ": "gfk", + "gga-Latn-SB": "gga", + "ggb-Latn-LR": "ggb", + "ggd-Latn-AU": "ggd", + "gge-Latn-AU": "gge", + "ggg-Arab-PK": "ggg", + "ggk-Latn-AU": "ggk", + "ggl-Latn-PG": "ggl", + "ggt-Latn-PG": "ggt", + "ggu-Latn-CI": "ggu", + "ggw-Latn-PG": "ggw", + "gha-Arab-LY": "gha", + "gha-Latn-LY": "gha-Latn", + "gha-Tfng-LY": "gha-Tfng", + "ghc-Latn-GB": "ghc", + "ghe-Deva-NP": "ghe", + "ghk-Latn-MM": "ghk", + "ghn-Latn-SB": "ghn", + "ghr-Arab-PK": "ghr", + "ghs-Latn-ZZ": "ghs", + "ght-Tibt-NP": "ght", + "gia-Latn-AU": "gia", + "gib-Latn-NG": "gib", + "gic-Latn-ZA": "gic", + "gid-Latn-CM": "gid", + "gie-Latn-CI": "gie", + "gig-Arab-PK": "gig", + "gih-Latn-AU": "gih", + "gil-Latn-KI": "gil", + "gim-Latn-ZZ": "gim", + "gin-Cyrl-RU": "gin", + "gip-Latn-PG": "gip", + "giq-Latn-VN": "giq", + "gir-Latn-VN": "gir", + "gis-Latn-CM": "gis", + "git-Latn-CA": "git", + "gix-Latn-CD": "gix", + "giy-Latn-AU": "giy", + "giz-Latn-CM": "giz", + "gjk-Arab-PK": "gjk", + "gjm-Latn-AU": "gjm", + "gjn-Latn-ZZ": "gjn", + "gjr-Latn-AU": "gjr", + "gju-Arab-PK": "gju", + "gka-Latn-PG": "gka", + "gkd-Latn-PG": "gkd", + "gke-Latn-CM": "gke", + "gkn-Latn-ZZ": "gkn", + "gko-Latn-AU": "gko", + "gkp-Latn-ZZ": "gkp", + "gku-Latn-ZA": "gku", + "gl-Latn-ES": "gl", + "glb-Latn-NG": "glb", + "glc-Latn-TD": "glc", + "gld-Cyrl-RU": "gld", + "glh-Arab-AF": "glh", + "glj-Latn-TD": "glj", + "glk-Arab-IR": "glk", + "gll-Latn-AU": "gll", + "glo-Latn-NG": "glo", + "glr-Latn-LR": "glr", + "glu-Latn-TD": "glu", + "glw-Latn-NG": "glw", + "gma-Latn-AU": "gma", + "gmb-Latn-SB": "gmb", + "gmd-Latn-NG": "gmd", + "gmg-Latn-PG": "gmg", + "gmh-Latn-DE": "gmh", + "gmm-Latn-ZZ": "gmm", + "gmn-Latn-CM": "gmn", + "gmr-Latn-AU": "gmr", + "gmu-Latn-PG": "gmu", + "gmv-Ethi-ZZ": "gmv", + "gmx-Latn-TZ": "gmx", + "gmy-Linb-GR": "gmy", + "gmz-Latn-NG": "gmz", + "gn-Latn-PY": "gn", + "gna-Latn-BF": "gna", + "gnb-Latn-IN": "gnb", + "gnc-Latn-ES": "gnc", + "gnd-Latn-ZZ": "gnd", + "gne-Latn-NG": "gne", + "gng-Latn-ZZ": "gng", + "gnh-Latn-NG": "gnh", + "gni-Latn-AU": "gni", + "gnj-Latn-CI": "gnj", + "gnk-Latn-BW": "gnk", + "gnl-Latn-AU": "gnl", + "gnm-Latn-PG": "gnm", + "gnn-Latn-AU": "gnn", + "gnq-Latn-MY": "gnq", + "gnr-Latn-AU": "gnr", + "gnt-Latn-PG": "gnt", + "gnu-Latn-PG": "gnu", + "gnw-Latn-BO": "gnw", + "gnz-Latn-CF": "gnz", + "goa-Latn-CI": "goa", + "gob-Latn-CO": "gob", + "goc-Latn-PG": "goc", + "god-Latn-ZZ": "god", + "goe-Tibt-BT": "goe", + "gof-Ethi-ZZ": "gof", + "gog-Latn-TZ": "gog", + "goh-Latn-DE": "goh", + "goi-Latn-ZZ": "goi", + "gok-Deva-IN": "gok", + "gol-Latn-LR": "gol", + "gom-Deva-IN": "gom", + "gon-Telu-IN": "gon", + "goo-Latn-FJ": "goo", + "gop-Latn-ID": "gop", + "goq-Latn-ID": "goq", + "gor-Latn-ID": "gor", + "gos-Latn-NL": "gos", + "got-Goth-UA": "got", + "gou-Latn-CM": "gou", + "gov-Latn-CI": "gov", + "gow-Latn-TZ": "gow", + "gox-Latn-CD": "gox", + "goy-Latn-TD": "goy", + "gpa-Latn-NG": "gpa", + "gpe-Latn-GH": "gpe", + "gpn-Latn-PG": "gpn", + "gqa-Latn-NG": "gqa", + "gqn-Latn-BR": "gqn", + "gqr-Latn-TD": "gqr", + "gra-Deva-IN": "gra", + "gra-Gujr-IN": "gra-Gujr", + "grb-Latn-ZZ": "grb", + "grc-Cprt-CY": "grc", + "grc-Linb-GR": "grc-Linb", + "grd-Latn-NG": "grd", + "grg-Latn-PG": "grg", + "grh-Latn-NG": "grh", + "gri-Latn-SB": "gri", + "grj-Latn-LR": "grj", + "grm-Latn-MY": "grm", + "grq-Latn-PG": "grq", + "grs-Latn-ID": "grs", + "grt-Beng-IN": "grt", + "gru-Ethi-ET": "gru", + "gru-Latn-ET": "gru-Latn", + "grv-Latn-LR": "grv", + "grw-Latn-ZZ": "grw", + "grx-Latn-PG": "grx", + "gry-Latn-LR": "gry", + "grz-Latn-PG": "grz", + "gsl-Latn-SN": "gsl", + "gsn-Latn-PG": "gsn", + "gso-Latn-CF": "gso", + "gsp-Latn-PG": "gsp", + "gsw-Latn-CH": "gsw", + "gta-Latn-BR": "gta", + "gtu-Latn-AU": "gtu", + "gu-Gujr-IN": "gu", + "gua-Latn-NG": "gua", + "gub-Latn-BR": "gub", + "guc-Latn-CO": "guc", + "gud-Latn-ZZ": "gud", + "gue-Latn-AU": "gue", + "guf-Latn-AU": "guf", + "guh-Latn-CO": "guh", + "gui-Latn-BO": "gui", + "guk-Ethi-ET": "guk-Ethi", + "guk-Latn-ET": "guk", + "gul-Latn-US": "gul", + "gum-Latn-CO": "gum", + "gun-Latn-BR": "gun", + "guo-Latn-CO": "guo", + "gup-Latn-AU": "gup", + "guq-Latn-PY": "guq", + "gur-Latn-GH": "gur", + "gut-Latn-CR": "gut", + "guu-Latn-VE": "guu", + "guw-Latn-ZZ": "guw", + "gux-Latn-ZZ": "gux", + "guz-Latn-KE": "guz", + "gv-Latn-IM": "gv", + "gva-Latn-PY": "gva", + "gvc-Latn-BR": "gvc", + "gve-Latn-PG": "gve", + "gvf-Latn-ZZ": "gvf", + "gvj-Latn-BR": "gvj", + "gvl-Latn-TD": "gvl", + "gvm-Latn-NG": "gvm", + "gvn-Latn-AU": "gvn", + "gvo-Latn-BR": "gvo", + "gvp-Latn-BR": "gvp", + "gvr-Deva-NP": "gvr", + "gvs-Latn-ZZ": "gvs", + "gvy-Latn-AU": "gvy", + "gwa-Latn-CI": "gwa", + "gwb-Latn-NG": "gwb", + "gwc-Arab-ZZ": "gwc", + "gwd-Latn-ET": "gwd", + "gwe-Latn-TZ": "gwe", + "gwf-Arab-PK": "gwf", + "gwg-Latn-NG": "gwg", + "gwi-Latn-CA": "gwi", + "gwj-Latn-BW": "gwj", + "gwm-Latn-AU": "gwm", + "gwn-Latn-NG": "gwn", + "gwr-Latn-UG": "gwr", + "gwt-Arab-ZZ": "gwt", + "gwu-Latn-AU": "gwu", + "gww-Latn-AU": "gww", + "gwx-Latn-GH": "gwx", + "gxx-Latn-CI": "gxx", + "gyb-Latn-PG": "gyb", + "gyd-Latn-AU": "gyd", + "gye-Latn-NG": "gye", + "gyf-Latn-AU": "gyf", + "gyg-Latn-CF": "gyg", + "gyi-Latn-ZZ": "gyi", + "gyl-Ethi-ET": "gyl-Ethi", + "gyl-Latn-ET": "gyl", + "gym-Latn-PA": "gym", + "gyn-Latn-GY": "gyn", + "gyo-Deva-NP": "gyo", + "gyr-Latn-BO": "gyr", + "gyy-Latn-AU": "gyy", + "gyz-Latn-NG": "gyz", + "gza-Latn-SD": "gza", + "gzi-Arab-IR": "gzi", + "gzn-Latn-ID": "gzn", + "ha-Arab-CM": "ha-CM", + "ha-Arab-NG": "ha-Arab", + "ha-Arab-SD": "ha-SD", + "ha-Latn-NE": "ha-NE", + "ha-Latn-NG": "ha", + "haa-Latn-US": "haa", + "hac-Arab-IR": "hac", + "had-Latn-ID": "had", + "hae-Latn-ET": "hae", + "hag-Latn-ZZ": "hag", + "hah-Latn-PG": "hah", + "hai-Latn-CA": "hai", + "haj-Beng-IN": "haj-Beng", + "haj-Latn-IN": "haj", + "hak-Hans-CN": "hak", + "hal-Latn-VN": "hal", + "ham-Latn-ZZ": "ham", + "han-Latn-TZ": "han", + "hao-Latn-PG": "hao", + "hap-Latn-ID": "hap", + "haq-Latn-TZ": "haq", + "har-Arab-ET": "har-Arab", + "har-Ethi-ET": "har", + "har-Latn-ET": "har-Latn", + "has-Latn-CA": "has", + "hav-Latn-CD": "hav", + "haw-Latn-US": "haw", + "hax-Latn-CA": "hax", + "hay-Latn-TZ": "hay", + "haz-Arab-AF": "haz", + "hba-Latn-CD": "hba", + "hbb-Latn-ZZ": "hbb", + "hbn-Latn-SD": "hbn", + "hbo-Hebr-IL": "hbo", + "hbu-Latn-TL": "hbu", + "hch-Latn-MX": "hch", + "hdy-Ethi-ZZ": "hdy", + "he-Hebr-IL": "he", + "hed-Latn-TD": "hed", + "heg-Latn-ID": "heg", + "heh-Latn-TZ": "heh", + "hei-Latn-CA": "hei", + "hem-Latn-CD": "hem", + "hgm-Latn-NA": "hgm", + "hgw-Latn-PG": "hgw", + "hhi-Latn-PG": "hhi", + "hhr-Latn-SN": "hhr", + "hhy-Latn-ZZ": "hhy", + "hi-Deva-IN": "hi", + "hi-Latn-IN": "hi-Latn", + "hi-Mahj-IN": "hi-Mahj", + "hia-Latn-ZZ": "hia", + "hib-Latn-PE": "hib", + "hid-Latn-US": "hid", + "hif-Deva-FJ": "hif-Deva", + "hif-Latn-FJ": "hif", + "hig-Latn-ZZ": "hig", + "hih-Latn-ZZ": "hih", + "hii-Deva-IN": "hii-Deva", + "hii-Takr-IN": "hii", + "hij-Latn-CM": "hij", + "hik-Latn-ID": "hik", + "hil-Latn-PH": "hil", + "hio-Latn-BW": "hio", + "hir-Latn-BR": "hir", + "hit-Xsux-TR": "hit", + "hiw-Latn-VU": "hiw", + "hix-Latn-BR": "hix", + "hji-Latn-ID": "hji", + "hka-Latn-TZ": "hka", + "hke-Latn-CD": "hke", + "hkh-Arab-IN": "hkh", + "hkh-Deva-IN": "hkh-Deva", + "hkh-Latn-IN": "hkh-Latn", + "hkk-Latn-PG": "hkk", + "hla-Latn-ZZ": "hla", + "hlb-Deva-IN": "hlb", + "hld-Latn-VN": "hld", + "hlt-Latn-MM": "hlt", + "hlu-Hluw-TR": "hlu", + "hma-Latn-CN": "hma", + "hmb-Latn-ML": "hmb", + "hmd-Plrd-CN": "hmd", + "hmf-Latn-VN": "hmf", + "hmj-Bopo-CN": "hmj", + "hmm-Latn-CN": "hmm", + "hmn-Bopo-CN": "hmn-Bopo", + "hmn-Hmng-CN": "hmn-Hmng", + "hmn-Latn-CN": "hmn", + "hmp-Latn-CN": "hmp", + "hmq-Bopo-CN": "hmq", + "hmr-Latn-IN": "hmr", + "hms-Latn-CN": "hms", + "hmt-Latn-ZZ": "hmt", + "hmu-Latn-ID": "hmu", + "hmv-Latn-VN": "hmv", + "hmw-Latn-CN": "hmw", + "hmy-Latn-CN": "hmy", + "hmz-Latn-CN": "hmz", + "hmz-Plrd-CN": "hmz-Plrd", + "hna-Latn-CM": "hna", + "hnd-Arab-PK": "hnd", + "hne-Deva-IN": "hne", + "hng-Latn-AO": "hng", + "hnh-Latn-BW": "hnh", + "hni-Latn-CN": "hni", + "hnj-Hmng-LA": "hnj-Hmng-LA", + "hnj-Hmnp-US": "hnj", + "hnj-Laoo-AU": "hnj-AU", + "hnj-Laoo-CN": "hnj-CN", + "hnj-Laoo-FR": "hnj-FR", + "hnj-Laoo-GF": "hnj-GF", + "hnj-Laoo-LA": "hnj-LA", + "hnj-Laoo-MM": "hnj-MM", + "hnj-Laoo-SR": "hnj-SR", + "hnj-Laoo-TH": "hnj-TH", + "hnj-Laoo-US": "hnj-Laoo-US", + "hnj-Laoo-VN": "hnj-VN", + "hnn-Hano-PH": "hnn-Hano", + "hnn-Latn-PH": "hnn", + "hno-Arab-PK": "hno", + "hns-Latn-SR": "hns", + "ho-Latn-PG": "ho", + "hoa-Latn-SB": "hoa", + "hob-Latn-PG": "hob", + "hoc-Deva-IN": "hoc", + "hoc-Wara-IN": "hoc-Wara", + "hod-Latn-NG": "hod", + "hoe-Latn-NG": "hoe", + "hoh-Arab-OM": "hoh", + "hoi-Latn-US": "hoi", + "hoj-Deva-IN": "hoj", + "hol-Latn-AO": "hol", + "hom-Latn-SS": "hom", + "hoo-Latn-CD": "hoo", + "hop-Latn-US": "hop", + "hor-Latn-TD": "hor", + "hot-Latn-ZZ": "hot", + "hov-Latn-ID": "hov", + "how-Hani-CN": "how", + "hoy-Deva-IN": "hoy", + "hpo-Mymr-MM": "hpo", + "hr-Latn-HR": "hr", + "hra-Latn-IN": "hra", + "hrc-Latn-PG": "hrc", + "hre-Latn-VN": "hre", + "hrk-Latn-ID": "hrk", + "hrm-Hmng-CN": "hrm-Hmng", + "hrm-Latn-CN": "hrm", + "hro-Latn-VN": "hro", + "hrp-Latn-AU": "hrp", + "hrt-Syrc-TR": "hrt", + "hru-Latn-IN": "hru", + "hrw-Latn-PG": "hrw", + "hrx-Latn-BR": "hrx", + "hrz-Arab-IR": "hrz", + "hsb-Latn-DE": "hsb", + "hsn-Hans-CN": "hsn", + "hss-Arab-OM": "hss", + "ht-Latn-HT": "ht", + "hti-Latn-ID": "hti", + "hto-Latn-CO": "hto", + "hts-Latn-TZ": "hts", + "htu-Latn-ID": "htu", + "htx-Xsux-TR": "htx", + "hu-Hung-HU": "hu-Hung", + "hu-Latn-HU": "hu", + "hub-Latn-PE": "hub", + "huc-Latn-BW": "huc", + "hud-Latn-ID": "hud", + "hue-Latn-MX": "hue", + "huf-Latn-PG": "huf", + "hug-Latn-PE": "hug", + "huh-Latn-CL": "huh", + "hui-Latn-ZZ": "hui", + "huk-Latn-ID": "huk", + "hul-Latn-PG": "hul", + "hum-Latn-CD": "hum", + "hup-Latn-US": "hup", + "hur-Latn-CA": "hur", + "hus-Latn-MX": "hus", + "hut-Deva-NP": "hut", + "hut-Tibt-NP": "hut-Tibt", + "huu-Latn-PE": "huu", + "huv-Latn-MX": "huv", + "huw-Latn-ID": "huw", + "hux-Latn-PE": "hux", + "huy-Hebr-IL": "huy", + "huz-Cyrl-RU": "huz", + "hvc-Latn-HT": "hvc", + "hve-Latn-MX": "hve", + "hvk-Latn-NC": "hvk", + "hvn-Latn-ID": "hvn", + "hvv-Latn-MX": "hvv", + "hwa-Latn-CI": "hwa", + "hwc-Latn-US": "hwc", + "hwo-Latn-NG": "hwo", + "hy-Armn-AM": "hy", + "hya-Latn-CM": "hya", + "hyw-Armn-AM": "hyw", + "hz-Latn-NA": "hz", + "ia-Latn-001": "ia", + "iai-Latn-NC": "iai", + "ian-Latn-ZZ": "ian", + "iar-Latn-ZZ": "iar", + "iba-Latn-MY": "iba", + "ibb-Latn-NG": "ibb", + "ibd-Latn-AU": "ibd", + "ibe-Latn-NG": "ibe", + "ibg-Latn-PH": "ibg", + "ibh-Latn-VN": "ibh", + "ibl-Latn-PH": "ibl", + "ibm-Latn-NG": "ibm", + "ibn-Latn-NG": "ibn", + "ibr-Latn-NG": "ibr", + "ibu-Latn-ID": "ibu", + "iby-Latn-ZZ": "iby", + "ica-Latn-ZZ": "ica", + "ich-Latn-ZZ": "ich", + "icr-Latn-CO": "icr", + "id-Latn-ID": "id", + "ida-Latn-KE": "ida", + "idb-Latn-IN": "idb", + "idc-Latn-NG": "idc", + "idd-Latn-ZZ": "idd", + "ide-Latn-NG": "ide", + "idi-Latn-ZZ": "idi", + "idr-Latn-SS": "idr", + "ids-Latn-NG": "ids", + "idt-Latn-TL": "idt", + "idu-Latn-ZZ": "idu", + "ie-Latn-001": "ie", + "ifa-Latn-PH": "ifa", + "ifb-Latn-PH": "ifb", + "ife-Latn-TG": "ife", + "iff-Latn-VU": "iff", + "ifk-Latn-PH": "ifk", + "ifm-Latn-CG": "ifm", + "ifu-Latn-PH": "ifu", + "ify-Latn-PH": "ify", + "ig-Latn-NG": "ig", + "igb-Latn-ZZ": "igb", + "ige-Latn-ZZ": "ige", + "igg-Latn-PG": "igg", + "igl-Latn-NG": "igl", + "igm-Latn-PG": "igm", + "ign-Latn-BO": "ign", + "igo-Latn-PG": "igo", + "igs-Grek-001": "igs-Grek", + "igs-Latn-001": "igs", + "igw-Latn-NG": "igw", + "ihb-Latn-ID": "ihb", + "ihi-Latn-NG": "ihi", + "ihp-Latn-ID": "ihp", + "ihw-Latn-AU": "ihw", + "ii-Yiii-CN": "ii", + "iin-Latn-AU": "iin", + "ijc-Latn-NG": "ijc", + "ije-Latn-NG": "ije", + "ijj-Latn-ZZ": "ijj", + "ijn-Latn-NG": "ijn", + "ijs-Latn-NG": "ijs", + "ik-Latn-US": "ik", + "iki-Latn-NG": "iki", + "ikk-Latn-ZZ": "ikk", + "ikl-Latn-NG": "ikl", + "iko-Latn-NG": "iko", + "ikp-Latn-NG": "ikp", + "ikr-Latn-AU": "ikr", + "ikt-Cans-CA": "ikt-Cans", + "ikt-Latn-CA": "ikt", + "ikv-Latn-NG": "ikv", + "ikw-Latn-ZZ": "ikw", + "ikx-Latn-ZZ": "ikx", + "ikz-Latn-TZ": "ikz", + "ila-Latn-ID": "ila", + "ilb-Latn-ZM": "ilb", + "ilg-Latn-AU": "ilg", + "ili-Arab-CN": "ili-Arab", + "ili-Cyrl-KZ": "ili-Cyrl", + "ili-Latn-CN": "ili", + "ilk-Latn-PH": "ilk", + "ilm-Latn-MY": "ilm", + "ilo-Latn-PH": "ilo", + "ilp-Latn-PH": "ilp", + "ilu-Latn-ID": "ilu", + "ilv-Latn-NG": "ilv", + "imi-Latn-PG": "imi", + "iml-Latn-US": "iml", + "imn-Latn-PG": "imn", + "imo-Latn-ZZ": "imo", + "imr-Latn-ID": "imr", + "ims-Latn-IT": "ims", + "imt-Latn-SS": "imt", + "imy-Lyci-TR": "imy", + "inb-Latn-CO": "inb", + "ing-Latn-US": "ing", + "inh-Cyrl-RU": "inh", + "inj-Latn-CO": "inj", + "inn-Latn-PH": "inn", + "ino-Latn-PG": "ino", + "inp-Latn-PE": "inp", + "int-Mymr-MM": "int", + "io-Latn-001": "io", + "ior-Ethi-ET": "ior", + "iou-Latn-ZZ": "iou", + "iow-Latn-US": "iow", + "ipi-Latn-PG": "ipi", + "ipo-Latn-PG": "ipo", + "iqu-Latn-PE": "iqu", + "iqw-Latn-NG": "iqw", + "ire-Latn-ID": "ire", + "irh-Latn-ID": "irh", + "iri-Latn-ZZ": "iri", + "irk-Latn-TZ": "irk", + "irn-Latn-BR": "irn", + "iru-Mlym-IN": "iru-Mlym", + "iru-Taml-IN": "iru", + "irx-Latn-ID": "irx", + "iry-Latn-PH": "iry", + "is-Latn-IS": "is", + "isa-Latn-PG": "isa", + "isc-Latn-PE": "isc", + "isd-Latn-PH": "isd", + "ish-Latn-NG": "ish", + "isi-Latn-NG": "isi", + "isk-Arab-AF": "isk", + "isk-Cyrl-TJ": "isk-Cyrl", + "ism-Latn-ID": "ism", + "isn-Latn-TZ": "isn", + "iso-Latn-NG": "iso", + "ist-Latn-HR": "ist", + "isu-Latn-CM": "isu", + "it-Latn-IT": "it", + "it-Latn-SM": "it-SM", + "it-Latn-VA": "it-VA", + "itb-Latn-PH": "itb", + "itd-Latn-ID": "itd", + "ite-Latn-BO": "ite", + "iti-Latn-PH": "iti", + "itk-Hebr-IT": "itk", + "itl-Cyrl-RU": "itl", + "itm-Latn-NG": "itm", + "ito-Latn-BO": "ito", + "itr-Latn-PG": "itr", + "its-Latn-NG": "its", + "itt-Latn-PH": "itt", + "itv-Latn-PH": "itv", + "itw-Latn-NG": "itw", + "itx-Latn-ID": "itx", + "ity-Latn-PH": "ity", + "itz-Latn-GT": "itz", + "iu-Cans-CA": "iu", + "ium-Hani-CN": "ium-Hani", + "ium-Laoo-LA": "ium-Laoo", + "ium-Latn-CN": "ium", + "ium-Thai-TH": "ium-Thai", + "ivb-Latn-PH": "ivb", + "ivv-Latn-PH": "ivv", + "iwk-Latn-PH": "iwk", + "iwm-Latn-ZZ": "iwm", + "iwo-Latn-ID": "iwo", + "iws-Latn-ZZ": "iws", + "ixc-Latn-MX": "ixc", + "ixl-Latn-GT": "ixl", + "iya-Latn-NG": "iya", + "iyo-Latn-CM": "iyo", + "iyx-Latn-CG": "iyx", + "izh-Latn-RU": "izh", + "izr-Latn-NG": "izr", + "izz-Latn-NG": "izz", + "ja-Hira-JP": "ja-Hira", + "ja-Jpan-JP": "ja", + "ja-Kana-JP": "ja-Kana", + "jaa-Latn-BR": "jaa", + "jab-Latn-ZZ": "jab", + "jac-Latn-GT": "jac", + "jad-Arab-GN": "jad", + "jae-Latn-PG": "jae", + "jaf-Latn-NG": "jaf", + "jah-Latn-MY": "jah", + "jaj-Latn-SB": "jaj", + "jak-Latn-MY": "jak", + "jal-Latn-ID": "jal", + "jam-Latn-JM": "jam", + "jan-Latn-AU": "jan", + "jao-Latn-AU": "jao", + "jaq-Latn-ID": "jaq", + "jas-Latn-NC": "jas", + "jat-Arab-AF": "jat", + "jau-Latn-ID": "jau", + "jax-Latn-ID": "jax", + "jay-Latn-AU": "jay", + "jaz-Latn-NC": "jaz", + "jbe-Hebr-IL": "jbe", + "jbi-Latn-AU": "jbi", + "jbj-Latn-ID": "jbj", + "jbk-Latn-PG": "jbk", + "jbm-Latn-NG": "jbm", + "jbn-Arab-LY": "jbn", + "jbo-Latn-001": "jbo", + "jbr-Latn-ID": "jbr", + "jbt-Latn-BR": "jbt", + "jbu-Latn-ZZ": "jbu", + "jbw-Latn-AU": "jbw", + "jct-Cyrl-UA": "jct", + "jct-Latn-UA": "jct-Latn", + "jda-Tibt-IN": "jda", + "jdg-Arab-PK": "jdg", + "jdt-Cyrl-RU": "jdt", + "jdt-Hebr-RU": "jdt-Hebr", + "jdt-Latn-AZ": "jdt-Latn", + "jeb-Latn-PE": "jeb", + "jee-Deva-NP": "jee", + "jeh-Laoo-LA": "jeh-Laoo", + "jeh-Latn-VN": "jeh", + "jei-Latn-ID": "jei", + "jek-Latn-CI": "jek", + "jel-Latn-ID": "jel", + "jen-Latn-ZZ": "jen", + "jer-Latn-NG": "jer", + "jet-Latn-PG": "jet", + "jeu-Latn-TD": "jeu", + "jgb-Latn-CD": "jgb", + "jge-Geor-GE": "jge", + "jge-Hebr-IL": "jge-Hebr", + "jgk-Latn-ZZ": "jgk", + "jgo-Latn-CM": "jgo", + "jhi-Latn-MY": "jhi", + "jia-Latn-CM": "jia", + "jib-Latn-ZZ": "jib", + "jic-Latn-HN": "jic", + "jid-Latn-NG": "jid", + "jie-Latn-NG": "jie", + "jig-Latn-AU": "jig", + "jil-Latn-PG": "jil", + "jim-Latn-CM": "jim", + "jit-Latn-TZ": "jit", + "jiu-Latn-CN": "jiu", + "jiv-Latn-EC": "jiv", + "jiy-Latn-CN": "jiy", + "jje-Hang-KR": "jje", + "jjr-Latn-NG": "jjr", + "jka-Latn-ID": "jka", + "jkm-Brai-MM": "jkm-Brai", + "jkm-Latn-MM": "jkm-Latn", + "jkm-Mymr-MM": "jkm", + "jko-Latn-PG": "jko", + "jku-Latn-NG": "jku", + "jle-Latn-SD": "jle", + "jma-Latn-PG": "jma", + "jmb-Latn-NG": "jmb", + "jmc-Latn-TZ": "jmc", + "jmd-Latn-ID": "jmd", + "jmi-Latn-NG": "jmi", + "jml-Deva-NP": "jml", + "jmn-Latn-MM": "jmn", + "jmr-Latn-GH": "jmr", + "jms-Latn-NG": "jms", + "jmw-Latn-PG": "jmw", + "jmx-Latn-MX": "jmx", + "jna-Takr-IN": "jna", + "jnd-Arab-PK": "jnd", + "jng-Latn-AU": "jng", + "jni-Latn-NG": "jni", + "jnj-Ethi-ET": "jnj-Ethi", + "jnj-Latn-ET": "jnj", + "jnl-Deva-IN": "jnl", + "jns-Deva-IN": "jns", + "jns-Latn-IN": "jns-Latn", + "jns-Takr-IN": "jns-Takr", + "job-Latn-CD": "job", + "jod-Latn-CI": "jod", + "jog-Arab-PK": "jog", + "jor-Latn-BO": "jor", + "jow-Latn-ML": "jow", + "jpa-Hebr-PS": "jpa", + "jpr-Hebr-IL": "jpr", + "jqr-Latn-PE": "jqr", + "jra-Latn-ZZ": "jra", + "jrr-Latn-NG": "jrr", + "jrt-Latn-NG": "jrt", + "jru-Latn-VE": "jru", + "jua-Latn-BR": "jua", + "jub-Latn-NG": "jub", + "jud-Latn-CI": "jud", + "juh-Latn-NG": "juh", + "jui-Latn-AU": "jui", + "juk-Latn-NG": "juk", + "jul-Deva-NP": "jul", + "jum-Latn-SD": "jum", + "jun-Orya-IN": "jun", + "juo-Latn-NG": "juo", + "jup-Latn-BR": "jup", + "jur-Latn-BR": "jur", + "jut-Latn-DK": "jut", + "juu-Latn-NG": "juu", + "juw-Latn-NG": "juw", + "juy-Orya-IN": "juy", + "jv-Java-ID": "jv-Java", + "jv-Latn-ID": "jv", + "jvd-Latn-ID": "jvd", + "jvn-Latn-SR": "jvn", + "jwi-Latn-GH": "jwi", + "jya-Tibt-CN": "jya", + "jye-Hebr-IL": "jye", + "jyy-Latn-TD": "jyy", + "ka-Geor-GE": "ka", + "kaa-Cyrl-UZ": "kaa", + "kab-Latn-DZ": "kab", + "kac-Latn-MM": "kac", + "kad-Latn-ZZ": "kad", + "kag-Latn-MY": "kag", + "kah-Latn-CF": "kah", + "kai-Latn-ZZ": "kai", + "kaj-Latn-NG": "kaj", + "kak-Latn-PH": "kak", + "kam-Latn-KE": "kam", + "kao-Latn-ML": "kao", + "kap-Cyrl-RU": "kap", + "kaq-Latn-PE": "kaq", + "kav-Latn-BR": "kav", + "kaw-Kawi-ID": "kaw", + "kax-Latn-ID": "kax", + "kay-Latn-BR": "kay", + "kba-Latn-AU": "kba", + "kbb-Latn-BR": "kbb", + "kbc-Latn-BR": "kbc", + "kbd-Cyrl-RU": "kbd", + "kbd-Cyrl-TR": "kbd-TR", + "kbe-Latn-AU": "kbe", + "kbh-Latn-CO": "kbh", + "kbi-Latn-ID": "kbi", + "kbj-Latn-CD": "kbj", + "kbk-Latn-PG": "kbk", + "kbl-Latn-TD": "kbl", + "kbm-Latn-ZZ": "kbm", + "kbn-Latn-CF": "kbn", + "kbo-Latn-SS": "kbo", + "kbp-Latn-ZZ": "kbp", + "kbq-Latn-ZZ": "kbq", + "kbr-Ethi-ET": "kbr-Ethi", + "kbr-Latn-ET": "kbr", + "kbs-Latn-GA": "kbs", + "kbt-Latn-PG": "kbt", + "kbu-Arab-PK": "kbu", + "kbv-Latn-ID": "kbv", + "kbw-Latn-PG": "kbw", + "kbx-Latn-ZZ": "kbx", + "kby-Arab-NE": "kby", + "kbz-Latn-NG": "kbz", + "kca-Cyrl-RU": "kca", + "kcb-Latn-PG": "kcb", + "kcc-Latn-NG": "kcc", + "kcd-Latn-ID": "kcd", + "kce-Latn-NG": "kce", + "kcf-Latn-NG": "kcf", + "kcg-Latn-NG": "kcg", + "kch-Latn-NG": "kch", + "kci-Latn-NG": "kci", + "kcj-Latn-GW": "kcj", + "kck-Latn-ZW": "kck", + "kcl-Latn-ZZ": "kcl", + "kcm-Latn-CF": "kcm", + "kcn-Latn-UG": "kcn", + "kco-Latn-PG": "kco", + "kcp-Latn-SD": "kcp", + "kcq-Latn-NG": "kcq", + "kcs-Latn-NG": "kcs", + "kct-Latn-ZZ": "kct", + "kcu-Latn-TZ": "kcu", + "kcv-Latn-CD": "kcv", + "kcw-Latn-CD": "kcw", + "kcz-Latn-TZ": "kcz", + "kda-Latn-AU": "kda", + "kdc-Latn-TZ": "kdc", + "kdd-Latn-AU": "kdd", + "kde-Latn-TZ": "kde", + "kdf-Latn-PG": "kdf", + "kdg-Latn-CD": "kdg", + "kdh-Latn-TG": "kdh", + "kdi-Latn-UG": "kdi", + "kdj-Latn-UG": "kdj", + "kdk-Latn-NC": "kdk", + "kdl-Latn-ZZ": "kdl", + "kdm-Latn-NG": "kdm", + "kdn-Latn-ZW": "kdn", + "kdp-Latn-NG": "kdp", + "kdq-Beng-IN": "kdq", + "kdr-Cyrl-UA": "kdr-Cyrl", + "kdr-Latn-LT": "kdr", + "kdt-Thai-KH": "kdt-KH", + "kdt-Thai-LA": "kdt-LA", + "kdt-Thai-TH": "kdt", + "kdw-Latn-ID": "kdw", + "kdx-Latn-NG": "kdx", + "kdy-Latn-ID": "kdy", + "kdz-Latn-CM": "kdz", + "kea-Latn-CV": "kea", + "keb-Latn-GA": "keb", + "kec-Latn-SD": "kec", + "ked-Latn-TZ": "ked", + "kee-Latn-US": "kee", + "kef-Latn-TG": "kef", + "keg-Latn-SD": "keg", + "keh-Latn-PG": "keh", + "kei-Latn-ID": "kei", + "kek-Latn-GT": "kek", + "kel-Latn-CD": "kel", + "kem-Latn-TL": "kem", + "ken-Latn-CM": "ken", + "keo-Latn-UG": "keo", + "ker-Latn-TD": "ker", + "kes-Latn-NG": "kes", + "ket-Cyrl-RU": "ket", + "keu-Latn-TG": "keu", + "kew-Latn-PG": "kew", + "kex-Deva-IN": "kex", + "kex-Gujr-IN": "kex-Gujr", + "key-Telu-IN": "key", + "kez-Latn-ZZ": "kez", + "kfa-Knda-IN": "kfa", + "kfb-Deva-IN": "kfb", + "kfc-Telu-IN": "kfc", + "kfd-Knda-IN": "kfd", + "kfe-Taml-IN": "kfe", + "kff-Deva-IN": "kff-Deva", + "kff-Latn-IN": "kff", + "kff-Orya-IN": "kff-Orya", + "kff-Telu-IN": "kff-Telu", + "kfh-Mlym-IN": "kfh", + "kfi-Knda-IN": "kfi-Knda", + "kfi-Taml-IN": "kfi", + "kfk-Deva-IN": "kfk", + "kfk-Takr-IN": "kfk-Takr", + "kfl-Latn-CM": "kfl", + "kfm-Arab-IR": "kfm", + "kfn-Latn-CM": "kfn", + "kfo-Latn-CI": "kfo", + "kfp-Deva-IN": "kfp", + "kfq-Deva-IN": "kfq", + "kfr-Deva-IN": "kfr", + "kfs-Deva-IN": "kfs", + "kfv-Latn-IN": "kfv", + "kfw-Latn-IN": "kfw", + "kfx-Deva-IN": "kfx", + "kfx-Takr-IN": "kfx-Takr", + "kfy-Deva-IN": "kfy", + "kfz-Latn-BF": "kfz", + "kg-Latn-CD": "kg", + "kga-Latn-CI": "kga", + "kgb-Latn-ID": "kgb", + "kge-Latn-ID": "kge", + "kgf-Latn-ZZ": "kgf", + "kgj-Deva-NP": "kgj", + "kgk-Latn-BR": "kgk", + "kgl-Latn-AU": "kgl", + "kgm-Latn-BR": "kgm", + "kgo-Latn-SD": "kgo", + "kgp-Latn-BR": "kgp", + "kgq-Latn-ID": "kgq", + "kgr-Latn-ID": "kgr", + "kgs-Latn-AU": "kgs", + "kgt-Latn-NG": "kgt", + "kgu-Latn-PG": "kgu", + "kgv-Latn-ID": "kgv", + "kgw-Latn-ID": "kgw", + "kgx-Latn-ID": "kgx", + "kgy-Deva-NP": "kgy", + "kha-Latn-IN": "kha", + "khb-Talu-CN": "khb", + "khc-Latn-ID": "khc", + "khd-Latn-ID": "khd", + "khe-Latn-ID": "khe", + "khf-Thai-LA": "khf", + "khg-Tibt-CN": "khg", + "khh-Latn-ID": "khh", + "khj-Latn-NG": "khj", + "khl-Latn-PG": "khl", + "khn-Deva-IN": "khn", + "khp-Latn-ID": "khp", + "khq-Latn-ML": "khq", + "khr-Deva-IN": "khr-Deva", + "khr-Latn-IN": "khr", + "khs-Latn-ZZ": "khs", + "kht-Mymr-IN": "kht", + "khu-Latn-AO": "khu", + "khv-Cyrl-RU": "khv", + "khw-Arab-PK": "khw", + "khx-Latn-CD": "khx", + "khy-Latn-CD": "khy", + "khz-Latn-ZZ": "khz", + "ki-Latn-KE": "ki", + "kia-Latn-TD": "kia", + "kib-Latn-SD": "kib", + "kic-Latn-US": "kic", + "kid-Latn-CM": "kid", + "kie-Latn-TD": "kie", + "kif-Deva-NP": "kif", + "kig-Latn-ID": "kig", + "kih-Latn-PG": "kih", + "kij-Latn-ZZ": "kij", + "kil-Latn-NG": "kil", + "kim-Cyrl-RU": "kim", + "kio-Latn-US": "kio", + "kip-Deva-NP": "kip", + "kiq-Latn-ID": "kiq", + "kis-Latn-PG": "kis", + "kit-Latn-PG": "kit", + "kiu-Latn-TR": "kiu", + "kiv-Latn-TZ": "kiv", + "kiw-Latn-ZZ": "kiw", + "kix-Latn-IN": "kix", + "kiy-Latn-ID": "kiy", + "kiz-Latn-TZ": "kiz", + "kj-Latn-NA": "kj", + "kja-Latn-ID": "kja", + "kjb-Latn-GT": "kjb", + "kjc-Latn-ID": "kjc", + "kjd-Latn-ZZ": "kjd", + "kje-Latn-ID": "kje", + "kjg-Laoo-LA": "kjg", + "kjh-Cyrl-RU": "kjh", + "kji-Latn-SB": "kji", + "kjj-Latn-AZ": "kjj", + "kjk-Latn-ID": "kjk", + "kjl-Deva-NP": "kjl", + "kjm-Latn-VN": "kjm", + "kjn-Latn-AU": "kjn", + "kjo-Deva-IN": "kjo", + "kjp-Mymr-MM": "kjp", + "kjp-Thai-TH": "kjp-Thai", + "kjq-Latn-US": "kjq", + "kjr-Latn-ID": "kjr", + "kjs-Latn-ZZ": "kjs", + "kjt-Thai-TH": "kjt", + "kju-Latn-US": "kju", + "kjx-Latn-PG": "kjx", + "kjy-Latn-ZZ": "kjy", + "kk-Arab-AF": "kk-AF", + "kk-Arab-CN": "kk-CN", + "kk-Arab-IR": "kk-IR", + "kk-Arab-MN": "kk-MN", + "kk-Cyrl-KZ": "kk", + "kka-Latn-NG": "kka", + "kkb-Latn-ID": "kkb", + "kkc-Latn-ZZ": "kkc", + "kkd-Latn-NG": "kkd", + "kke-Arab-GN": "kke-Arab", + "kke-Latn-GN": "kke", + "kkf-Tibt-IN": "kkf", + "kkg-Latn-PH": "kkg", + "kkh-Lana-MM": "kkh", + "kki-Latn-TZ": "kki", + "kkj-Latn-CM": "kkj", + "kkk-Latn-SB": "kkk", + "kkl-Latn-ID": "kkl", + "kkm-Latn-NG": "kkm", + "kko-Latn-SD": "kko", + "kkp-Latn-AU": "kkp", + "kkq-Latn-CD": "kkq", + "kkr-Latn-NG": "kkr", + "kks-Latn-NG": "kks", + "kkt-Deva-NP": "kkt", + "kku-Latn-NG": "kku", + "kkv-Latn-ID": "kkv", + "kkw-Latn-CG": "kkw", + "kkx-Latn-ID": "kkx", + "kky-Latn-AU": "kky", + "kkz-Latn-CA": "kkz", + "kl-Latn-GL": "kl", + "kla-Latn-US": "kla", + "klb-Latn-MX": "klb", + "klc-Latn-CM": "klc", + "kld-Latn-AU": "kld", + "kle-Deva-NP": "kle", + "klf-Latn-TD": "klf", + "klg-Latn-PH": "klg", + "klh-Latn-PG": "klh", + "kli-Latn-ID": "kli", + "klj-Arab-IR": "klj", + "klk-Latn-NG": "klk", + "kll-Latn-PH": "kll", + "klm-Latn-PG": "klm", + "kln-Latn-KE": "kln", + "klo-Latn-NG": "klo", + "klp-Latn-PG": "klp", + "klq-Latn-ZZ": "klq", + "klr-Deva-NP": "klr", + "kls-Arab-PK": "kls-Arab", + "kls-Latn-PK": "kls", + "klt-Latn-ZZ": "klt", + "klu-Latn-LR": "klu", + "klv-Latn-VU": "klv", + "klw-Latn-ID": "klw", + "klx-Latn-ZZ": "klx", + "kly-Latn-ID": "kly", + "klz-Latn-ID": "klz", + "km-Khmr-KH": "km", + "kma-Latn-GH": "kma", + "kmb-Latn-AO": "kmb", + "kmc-Hani-CN": "kmc-Hani", + "kmc-Latn-CN": "kmc", + "kmd-Latn-PH": "kmd", + "kme-Latn-CM": "kme", + "kmf-Latn-PG": "kmf", + "kmg-Latn-PG": "kmg", + "kmh-Latn-ZZ": "kmh", + "kmi-Latn-NG": "kmi", + "kmj-Deva-IN": "kmj", + "kmk-Latn-PH": "kmk", + "kml-Latn-PH": "kml", + "kmm-Latn-IN": "kmm", + "kmn-Latn-PG": "kmn", + "kmo-Latn-ZZ": "kmo", + "kmp-Latn-CM": "kmp", + "kmq-Latn-ET": "kmq", + "kms-Latn-ZZ": "kms", + "kmt-Latn-ID": "kmt", + "kmu-Latn-ZZ": "kmu", + "kmv-Latn-BR": "kmv", + "kmw-Latn-ZZ": "kmw", + "kmx-Latn-PG": "kmx", + "kmy-Latn-NG": "kmy", + "kmz-Arab-IR": "kmz", + "kn-Knda-IN": "kn", + "kna-Latn-NG": "kna", + "knb-Latn-PH": "knb", + "knd-Latn-ID": "knd", + "kne-Latn-PH": "kne", + "knf-Latn-GW": "knf", + "kni-Latn-NG": "kni", + "knj-Latn-GT": "knj", + "knk-Arab-SL": "knk-Arab", + "knk-Latn-SL": "knk", + "knl-Latn-ID": "knl", + "knm-Latn-BR": "knm", + "kno-Latn-SL": "kno", + "knp-Latn-ZZ": "knp", + "knq-Latn-MY": "knq", + "knr-Latn-PG": "knr", + "kns-Latn-MY": "kns", + "kns-Thai-TH": "kns-Thai", + "knt-Latn-BR": "knt", + "knu-Latn-GN": "knu", + "knv-Latn-PG": "knv", + "knw-Latn-NA": "knw", + "knx-Latn-ID": "knx", + "kny-Latn-CD": "kny", + "knz-Latn-BF": "knz", + "ko-Hang-KR": "ko-Hang", + "ko-Jamo-KR": "ko-Jamo", + "ko-Kore-KP": "ko-KP", + "ko-Kore-KR": "ko", + "koa-Latn-PG": "koa", + "koc-Latn-NG": "koc", + "kod-Latn-ID": "kod", + "koe-Latn-SS": "koe", + "kof-Latn-NG": "kof", + "kog-Latn-CO": "kog", + "koh-Latn-CG": "koh", + "koi-Cyrl-RU": "koi", + "kok-Deva-IN": "kok", + "kol-Latn-ZZ": "kol", + "koo-Latn-UG": "koo", + "kop-Latn-PG": "kop", + "koq-Latn-GA": "koq", + "kos-Latn-FM": "kos", + "kot-Latn-CM": "kot", + "kou-Latn-TD": "kou", + "kov-Latn-NG": "kov", + "kow-Latn-NG": "kow", + "koy-Latn-US": "koy", + "koz-Latn-ZZ": "koz", + "kpa-Latn-NG": "kpa", + "kpc-Latn-CO": "kpc", + "kpd-Latn-ID": "kpd", + "kpe-Latn-LR": "kpe", + "kpf-Latn-ZZ": "kpf", + "kpg-Latn-FM": "kpg", + "kph-Latn-GH": "kph", + "kpi-Latn-ID": "kpi", + "kpj-Latn-BR": "kpj", + "kpk-Latn-NG": "kpk", + "kpl-Latn-CD": "kpl", + "kpm-Latn-VN": "kpm", + "kpn-Latn-BR": "kpn", + "kpo-Latn-ZZ": "kpo", + "kpq-Latn-ID": "kpq", + "kpr-Latn-ZZ": "kpr", + "kps-Latn-ID": "kps", + "kpt-Cyrl-RU": "kpt", + "kpu-Latn-ID": "kpu", + "kpw-Latn-PG": "kpw", + "kpx-Latn-ZZ": "kpx", + "kpy-Cyrl-RU": "kpy", + "kpz-Latn-UG": "kpz", + "kqa-Latn-PG": "kqa", + "kqb-Latn-ZZ": "kqb", + "kqc-Latn-PG": "kqc", + "kqd-Syrc-IQ": "kqd", + "kqe-Latn-PH": "kqe", + "kqf-Latn-ZZ": "kqf", + "kqg-Latn-BF": "kqg", + "kqh-Latn-TZ": "kqh", + "kqi-Latn-PG": "kqi", + "kqj-Latn-PG": "kqj", + "kqk-Latn-BJ": "kqk", + "kql-Latn-PG": "kql", + "kqm-Latn-CI": "kqm", + "kqn-Latn-ZM": "kqn", + "kqo-Latn-LR": "kqo", + "kqp-Latn-TD": "kqp", + "kqq-Latn-BR": "kqq", + "kqr-Latn-MY": "kqr", + "kqs-Latn-ZZ": "kqs", + "kqt-Latn-MY": "kqt", + "kqu-Latn-ZA": "kqu", + "kqv-Latn-ID": "kqv", + "kqw-Latn-PG": "kqw", + "kqx-Latn-CM": "kqx", + "kqy-Ethi-ZZ": "kqy", + "kqz-Latn-ZA": "kqz", + "kr-Latn-ZZ": "kr", + "kra-Deva-NP": "kra", + "krb-Latn-US": "krb", + "krc-Cyrl-RU": "krc", + "krd-Latn-TL": "krd", + "kre-Latn-BR": "kre", + "krf-Latn-VU": "krf", + "krh-Latn-NG": "krh", + "kri-Latn-SL": "kri", + "krj-Latn-PH": "krj", + "krk-Cyrl-RU": "krk", + "krl-Latn-RU": "krl", + "krn-Latn-LR": "krn", + "krp-Latn-NG": "krp", + "krr-Khmr-KH": "krr", + "krs-Latn-ZZ": "krs", + "krt-Latn-NE": "krt", + "kru-Deva-IN": "kru", + "krv-Khmr-KH": "krv", + "krw-Latn-LR": "krw", + "krx-Latn-SN": "krx", + "kry-Latn-AZ": "kry", + "krz-Latn-ID": "krz", + "ks-Arab-IN": "ks", + "ksa-Latn-NG": "ksa", + "ksb-Latn-TZ": "ksb", + "ksc-Latn-PH": "ksc", + "ksd-Latn-ZZ": "ksd", + "kse-Latn-PG": "kse", + "ksf-Latn-CM": "ksf", + "ksg-Latn-SB": "ksg", + "ksh-Latn-DE": "ksh", + "ksi-Latn-PG": "ksi", + "ksj-Latn-ZZ": "ksj", + "ksk-Latn-US": "ksk", + "ksl-Latn-PG": "ksl", + "ksm-Latn-NG": "ksm", + "ksn-Latn-PH": "ksn", + "kso-Latn-NG": "kso", + "ksp-Latn-CF": "ksp", + "ksq-Latn-NG": "ksq", + "ksr-Latn-ZZ": "ksr", + "kss-Latn-LR": "kss", + "kst-Latn-BF": "kst", + "ksu-Mymr-IN": "ksu", + "ksv-Latn-CD": "ksv", + "ksw-Latn-MM": "ksw-Latn", + "ksw-Mymr-MM": "ksw", + "ksx-Latn-ID": "ksx", + "ksz-Deva-IN": "ksz", + "kta-Latn-VN": "kta", + "ktb-Ethi-ZZ": "ktb", + "ktc-Latn-NG": "ktc", + "ktd-Latn-AU": "ktd", + "ktf-Latn-CD": "ktf", + "ktg-Latn-AU": "ktg", + "kth-Latn-TD": "kth", + "kti-Latn-ID": "kti", + "ktj-Latn-CI": "ktj", + "ktk-Latn-PG": "ktk", + "ktl-Arab-IR": "ktl", + "ktm-Latn-ZZ": "ktm", + "ktn-Latn-BR": "ktn", + "kto-Latn-ZZ": "kto", + "ktp-Plrd-CN": "ktp", + "ktq-Latn-PH": "ktq", + "kts-Latn-ID": "kts", + "ktt-Latn-ID": "ktt", + "ktu-Latn-CD": "ktu", + "ktv-Latn-VN": "ktv", + "ktw-Latn-US": "ktw", + "ktx-Latn-BR": "ktx", + "kty-Latn-CD": "kty", + "ktz-Latn-NA": "ktz", + "ku-Arab-IQ": "ku-Arab", + "ku-Arab-LB": "ku-LB", + "ku-Latn-AM": "ku-AM", + "ku-Latn-GE": "ku-GE", + "ku-Latn-TR": "ku", + "ku-Yezi-GE": "ku-Yezi", + "kub-Latn-ZZ": "kub", + "kuc-Latn-ID": "kuc", + "kud-Latn-ZZ": "kud", + "kue-Latn-ZZ": "kue", + "kuf-Laoo-LA": "kuf", + "kug-Latn-NG": "kug", + "kuh-Latn-NG": "kuh", + "kui-Latn-BR": "kui", + "kuj-Latn-ZZ": "kuj", + "kuk-Latn-ID": "kuk", + "kul-Latn-NG": "kul", + "kum-Cyrl-RU": "kum", + "kun-Latn-ZZ": "kun", + "kuo-Latn-PG": "kuo", + "kup-Latn-ZZ": "kup", + "kuq-Latn-BR": "kuq", + "kus-Latn-ZZ": "kus", + "kut-Latn-CA": "kut", + "kuu-Latn-US": "kuu", + "kuv-Latn-ID": "kuv", + "kuw-Latn-CF": "kuw", + "kux-Latn-AU": "kux", + "kuy-Latn-AU": "kuy", + "kuz-Latn-CL": "kuz", + "kv-Cyrl-RU": "kv", + "kv-Perm-RU": "kv-Perm", + "kva-Cyrl-RU": "kva", + "kvb-Latn-ID": "kvb", + "kvc-Latn-PG": "kvc", + "kvd-Latn-ID": "kvd", + "kve-Latn-MY": "kve", + "kvf-Latn-TD": "kvf", + "kvg-Latn-ZZ": "kvg", + "kvh-Latn-ID": "kvh", + "kvi-Latn-TD": "kvi", + "kvj-Latn-CM": "kvj", + "kvl-Latn-MM": "kvl", + "kvm-Latn-CM": "kvm", + "kvn-Latn-CO": "kvn", + "kvo-Latn-ID": "kvo", + "kvp-Latn-ID": "kvp", + "kvq-Latn-MM": "kvq-Latn", + "kvq-Mymr-MM": "kvq", + "kvr-Latn-ID": "kvr", + "kvt-Mymr-MM": "kvt", + "kvv-Latn-ID": "kvv", + "kvw-Latn-ID": "kvw", + "kvx-Arab-PK": "kvx", + "kvy-Kali-MM": "kvy", + "kvz-Latn-ID": "kvz", + "kw-Latn-GB": "kw", + "kwa-Latn-BR": "kwa", + "kwb-Latn-NG": "kwb", + "kwc-Latn-CG": "kwc", + "kwd-Latn-SB": "kwd", + "kwe-Latn-ID": "kwe", + "kwf-Latn-SB": "kwf", + "kwg-Latn-TD": "kwg", + "kwh-Latn-ID": "kwh", + "kwi-Latn-CO": "kwi", + "kwj-Latn-ZZ": "kwj", + "kwk-Latn-CA": "kwk", + "kwl-Latn-NG": "kwl", + "kwm-Latn-NA": "kwm", + "kwn-Latn-NA": "kwn", + "kwo-Latn-ZZ": "kwo", + "kwp-Latn-CI": "kwp", + "kwr-Latn-ID": "kwr", + "kws-Latn-CD": "kws", + "kwt-Latn-ID": "kwt", + "kwu-Latn-CM": "kwu", + "kwv-Latn-TD": "kwv", + "kww-Latn-SR": "kww", + "kwy-Latn-CD": "kwy", + "kwz-Latn-AO": "kwz", + "kxa-Latn-ZZ": "kxa", + "kxb-Latn-CI": "kxb", + "kxc-Ethi-ZZ": "kxc", + "kxd-Arab-BN": "kxd-Arab", + "kxd-Latn-BN": "kxd", + "kxf-Latn-MM": "kxf-Latn", + "kxf-Mymr-MM": "kxf", + "kxi-Latn-MY": "kxi", + "kxj-Latn-TD": "kxj", + "kxk-Mymr-MM": "kxk", + "kxm-Thai-TH": "kxm", + "kxn-Latn-MY": "kxn", + "kxo-Latn-BR": "kxo", + "kxp-Arab-PK": "kxp", + "kxq-Latn-ID": "kxq", + "kxr-Latn-PG": "kxr", + "kxt-Latn-PG": "kxt", + "kxv-Latn-IN": "kxv-Latn", + "kxv-Orya-IN": "kxv", + "kxv-Telu-IN": "kxv-Telu", + "kxw-Latn-ZZ": "kxw", + "kxx-Latn-CG": "kxx", + "kxy-Latn-VN": "kxy", + "kxz-Latn-ZZ": "kxz", + "ky-Arab-CN": "ky-CN", + "ky-Cyrl-KG": "ky", + "ky-Latn-TR": "ky-TR", + "kya-Latn-TZ": "kya", + "kyb-Latn-PH": "kyb", + "kyc-Latn-PG": "kyc", + "kyd-Latn-ID": "kyd", + "kye-Latn-ZZ": "kye", + "kyf-Latn-CI": "kyf", + "kyg-Latn-PG": "kyg", + "kyh-Latn-US": "kyh", + "kyi-Latn-MY": "kyi", + "kyj-Latn-PH": "kyj", + "kyk-Latn-PH": "kyk", + "kyl-Latn-US": "kyl", + "kym-Latn-CF": "kym", + "kyn-Latn-PH": "kyn", + "kyo-Latn-ID": "kyo", + "kyq-Latn-TD": "kyq", + "kyr-Latn-BR": "kyr", + "kys-Latn-MY": "kys", + "kyt-Latn-ID": "kyt", + "kyu-Kali-MM": "kyu", + "kyu-Latn-MM": "kyu-Latn", + "kyu-Mymr-MM": "kyu-Mymr", + "kyv-Deva-NP": "kyv", + "kyw-Beng-IN": "kyw-Beng", + "kyw-Deva-IN": "kyw", + "kyw-Orya-IN": "kyw-Orya", + "kyx-Latn-ZZ": "kyx", + "kyy-Latn-PG": "kyy", + "kyz-Latn-BR": "kyz", + "kza-Latn-BF": "kza", + "kzb-Latn-ID": "kzb", + "kzc-Latn-CI": "kzc", + "kzd-Latn-ID": "kzd", + "kze-Latn-PG": "kze", + "kzf-Latn-ID": "kzf", + "kzi-Latn-MY": "kzi", + "kzk-Latn-SB": "kzk", + "kzl-Latn-ID": "kzl", + "kzm-Latn-ID": "kzm", + "kzn-Latn-MW": "kzn", + "kzo-Latn-GA": "kzo", + "kzp-Latn-ID": "kzp", + "kzr-Latn-ZZ": "kzr", + "kzs-Latn-MY": "kzs", + "kzu-Latn-ID": "kzu", + "kzv-Latn-ID": "kzv", + "kzw-Latn-BR": "kzw", + "kzx-Latn-ID": "kzx", + "kzy-Latn-CD": "kzy", + "kzz-Latn-ID": "kzz", + "la-Latn-VA": "la", + "laa-Latn-PH": "laa", + "lab-Lina-GR": "lab", + "lac-Latn-MX": "lac", + "lad-Hebr-IL": "lad", + "lae-Deva-IN": "lae", + "lae-Tibt-IN": "lae-Tibt", + "lag-Latn-TZ": "lag", + "lah-Arab-PK": "lah", + "lai-Latn-MW": "lai", + "laj-Latn-UG": "laj", + "lal-Latn-CD": "lal", + "lam-Latn-ZM": "lam", + "lan-Latn-NG": "lan", + "lap-Latn-TD": "lap", + "laq-Latn-VN": "laq", + "lar-Latn-GH": "lar", + "las-Latn-ZZ": "las", + "lau-Latn-ID": "lau", + "law-Latn-ID": "law", + "lax-Beng-IN": "lax-Beng", + "lax-Latn-IN": "lax", + "laz-Latn-PG": "laz", + "lb-Latn-LU": "lb", + "lbb-Latn-PG": "lbb", + "lbc-Lisu-CN": "lbc", + "lbe-Cyrl-RU": "lbe", + "lbf-Deva-IN": "lbf", + "lbf-Tibt-CN": "lbf-Tibt", + "lbi-Latn-CM": "lbi", + "lbj-Arab-IN": "lbj-Arab", + "lbj-Tibt-IN": "lbj", + "lbl-Latn-PH": "lbl", + "lbm-Deva-IN": "lbm", + "lbn-Laoo-LA": "lbn-Laoo", + "lbn-Latn-LA": "lbn", + "lbo-Laoo-LA": "lbo", + "lbo-Latn-US": "lbo-Latn", + "lbq-Latn-PG": "lbq", + "lbr-Deva-NP": "lbr", + "lbt-Latn-VN": "lbt", + "lbu-Latn-ZZ": "lbu", + "lbv-Latn-PG": "lbv", + "lbw-Latn-ID": "lbw", + "lbx-Latn-ID": "lbx", + "lby-Latn-AU": "lby", + "lbz-Latn-AU": "lbz", + "lcc-Latn-ID": "lcc", + "lcd-Latn-ID": "lcd", + "lce-Latn-ID": "lce", + "lcf-Latn-ID": "lcf", + "lch-Latn-AO": "lch", + "lcl-Latn-ID": "lcl", + "lcm-Latn-ZZ": "lcm", + "lcp-Thai-CN": "lcp", + "lcq-Latn-ID": "lcq", + "lcs-Latn-ID": "lcs", + "lda-Latn-CI": "lda", + "ldb-Latn-ZZ": "ldb", + "ldd-Latn-NG": "ldd", + "ldg-Latn-NG": "ldg", + "ldh-Latn-NG": "ldh", + "ldi-Latn-CG": "ldi", + "ldj-Latn-NG": "ldj", + "ldk-Latn-NG": "ldk", + "ldl-Latn-NG": "ldl", + "ldm-Latn-GN": "ldm", + "ldn-Latn-001": "ldn", + "ldo-Latn-NG": "ldo", + "ldp-Latn-NG": "ldp", + "ldq-Latn-NG": "ldq", + "lea-Latn-CD": "lea", + "leb-Latn-ZM": "leb", + "lec-Latn-BO": "lec", + "led-Latn-ZZ": "led", + "lee-Latn-ZZ": "lee", + "lef-Latn-GH": "lef", + "leh-Latn-ZM": "leh", + "lei-Latn-PG": "lei", + "lej-Latn-CD": "lej", + "lek-Latn-PG": "lek", + "lel-Latn-CD": "lel", + "lem-Latn-ZZ": "lem", + "len-Latn-HN": "len", + "leo-Latn-CM": "leo", + "lep-Lepc-IN": "lep", + "leq-Latn-ZZ": "leq", + "ler-Latn-PG": "ler", + "les-Latn-CD": "les", + "let-Latn-PG": "let", + "leu-Latn-ZZ": "leu", + "lev-Latn-ID": "lev", + "lew-Latn-ID": "lew", + "lex-Latn-ID": "lex", + "ley-Latn-ID": "ley", + "lez-Cyrl-RU": "lez", + "lfa-Latn-CM": "lfa", + "lfn-Cyrl-001": "lfn-Cyrl", + "lfn-Latn-001": "lfn", + "lg-Latn-UG": "lg", + "lga-Latn-SB": "lga", + "lgb-Latn-SB": "lgb", + "lgg-Latn-ZZ": "lgg", + "lgh-Latn-VN": "lgh", + "lgi-Latn-ID": "lgi", + "lgk-Latn-VU": "lgk", + "lgl-Latn-SB": "lgl", + "lgm-Latn-CD": "lgm", + "lgn-Latn-ET": "lgn", + "lgo-Latn-SS": "lgo", + "lgq-Latn-GH": "lgq", + "lgr-Latn-SB": "lgr", + "lgt-Latn-PG": "lgt", + "lgu-Latn-SB": "lgu", + "lgz-Latn-CD": "lgz", + "lha-Latn-VN": "lha", + "lhh-Latn-ID": "lhh", + "lhi-Latn-CN": "lhi", + "lhm-Deva-NP": "lhm", + "lhn-Latn-MY": "lhn", + "lhs-Syrc-SY": "lhs", + "lht-Latn-VU": "lht", + "lhu-Latn-CN": "lhu", + "li-Latn-NL": "li", + "lia-Latn-ZZ": "lia", + "lib-Latn-PG": "lib", + "lic-Latn-CN": "lic", + "lid-Latn-ZZ": "lid", + "lie-Latn-CD": "lie", + "lif-Deva-NP": "lif", + "lif-Limb-IN": "lif-Limb", + "lig-Latn-ZZ": "lig", + "lih-Latn-ZZ": "lih", + "lij-Latn-IT": "lij", + "lik-Latn-CD": "lik", + "lil-Latn-CA": "lil", + "lio-Latn-ID": "lio", + "lip-Latn-GH": "lip", + "liq-Latn-ET": "liq", + "lir-Latn-LR": "lir", + "lis-Lisu-CN": "lis", + "liu-Latn-SD": "liu", + "liv-Latn-LV": "liv", + "liw-Latn-ID": "liw", + "lix-Latn-ID": "lix", + "liy-Latn-CF": "liy", + "liz-Latn-CD": "liz", + "lja-Latn-AU": "lja", + "lje-Latn-ID": "lje", + "lji-Latn-ID": "lji", + "ljl-Latn-ID": "ljl", + "ljp-Latn-ID": "ljp", + "ljw-Latn-AU": "ljw", + "ljx-Latn-AU": "ljx", + "lka-Latn-TL": "lka", + "lkb-Latn-KE": "lkb", + "lkc-Latn-VN": "lkc", + "lkd-Latn-BR": "lkd", + "lke-Latn-UG": "lke", + "lkh-Tibt-BT": "lkh", + "lki-Arab-IR": "lki", + "lkj-Latn-MY": "lkj", + "lkl-Latn-PG": "lkl", + "lkm-Latn-AU": "lkm", + "lkn-Latn-VU": "lkn", + "lko-Latn-KE": "lko", + "lkr-Latn-SS": "lkr", + "lks-Latn-KE": "lks", + "lkt-Latn-US": "lkt", + "lku-Latn-AU": "lku", + "lky-Latn-SS": "lky", + "lla-Latn-NG": "lla", + "llb-Latn-MZ": "llb", + "llc-Latn-GN": "llc", + "lld-Latn-IT": "lld", + "lle-Latn-ZZ": "lle", + "llf-Latn-PG": "llf", + "llg-Latn-ID": "llg", + "lli-Latn-CG": "lli", + "llj-Latn-AU": "llj", + "llk-Latn-MY": "llk", + "lll-Latn-PG": "lll", + "llm-Latn-ID": "llm", + "lln-Latn-ZZ": "lln", + "llp-Latn-VU": "llp", + "llq-Latn-ID": "llq", + "llu-Latn-SB": "llu", + "llx-Latn-FJ": "llx", + "lma-Latn-GN": "lma", + "lmb-Latn-VU": "lmb", + "lmc-Latn-AU": "lmc", + "lmd-Latn-SD": "lmd", + "lme-Latn-TD": "lme", + "lmf-Latn-ID": "lmf", + "lmg-Latn-PG": "lmg", + "lmh-Deva-NP": "lmh", + "lmi-Latn-CD": "lmi", + "lmj-Latn-ID": "lmj", + "lmk-Latn-IN": "lmk", + "lmk-Mymr-IN": "lmk-Mymr", + "lml-Latn-VU": "lml", + "lmn-Telu-IN": "lmn", + "lmo-Latn-IT": "lmo", + "lmp-Latn-ZZ": "lmp", + "lmq-Latn-ID": "lmq", + "lmr-Latn-ID": "lmr", + "lmu-Latn-VU": "lmu", + "lmv-Latn-FJ": "lmv", + "lmw-Latn-US": "lmw", + "lmx-Latn-CM": "lmx", + "lmy-Latn-ID": "lmy", + "ln-Latn-CD": "ln", + "lna-Latn-CF": "lna", + "lnb-Latn-NA": "lnb", + "lnd-Latn-ID": "lnd", + "lnh-Latn-MY": "lnh", + "lni-Latn-PG": "lni", + "lnj-Latn-AU": "lnj", + "lnl-Latn-CF": "lnl", + "lnm-Latn-PG": "lnm", + "lnn-Latn-VU": "lnn", + "lns-Latn-ZZ": "lns", + "lnu-Latn-ZZ": "lnu", + "lnw-Latn-AU": "lnw", + "lnz-Latn-CD": "lnz", + "lo-Laoo-LA": "lo", + "loa-Latn-ID": "loa", + "lob-Latn-BF": "lob", + "loc-Latn-PH": "loc", + "loe-Latn-ID": "loe", + "log-Latn-CD": "log", + "loh-Latn-SS": "loh", + "loi-Latn-CI": "loi", + "loj-Latn-ZZ": "loj", + "lok-Latn-ZZ": "lok", + "lol-Latn-CD": "lol", + "lom-Latn-LR": "lom", + "lon-Latn-MW": "lon", + "loo-Latn-CD": "loo", + "lop-Latn-NG": "lop", + "loq-Latn-CD": "loq", + "lor-Latn-ZZ": "lor", + "los-Latn-ZZ": "los", + "lot-Arab-SS": "lot-Arab", + "lot-Latn-SS": "lot", + "lou-Latn-US": "lou", + "low-Latn-MY": "low", + "lox-Latn-ID": "lox", + "loy-Deva-NP": "loy", + "loy-Tibt-NP": "loy-Tibt", + "loz-Latn-ZM": "loz", + "lpa-Latn-VU": "lpa", + "lpe-Latn-ID": "lpe", + "lpn-Latn-MM": "lpn", + "lpo-Lisu-CN": "lpo-Lisu", + "lpo-Plrd-CN": "lpo", + "lpx-Latn-SS": "lpx", + "lqr-Latn-SS": "lqr", + "lra-Latn-MY": "lra", + "lrc-Arab-IR": "lrc", + "lrg-Latn-AU": "lrg", + "lri-Latn-KE": "lri", + "lrk-Arab-PK": "lrk", + "lrl-Arab-IR": "lrl", + "lrm-Latn-KE": "lrm", + "lrn-Latn-ID": "lrn", + "lro-Latn-SD": "lro", + "lrt-Latn-ID": "lrt", + "lrv-Latn-VU": "lrv", + "lrz-Latn-VU": "lrz", + "lsa-Arab-IR": "lsa", + "lsd-Hebr-IL": "lsd", + "lse-Latn-CD": "lse", + "lsi-Latn-MM": "lsi", + "lsm-Latn-UG": "lsm", + "lsr-Latn-PG": "lsr", + "lss-Arab-PK": "lss", + "lt-Latn-LT": "lt", + "ltg-Latn-LV": "ltg", + "lth-Latn-UG": "lth", + "lti-Latn-ID": "lti", + "ltn-Latn-BR": "ltn", + "lto-Latn-KE": "lto", + "lts-Latn-KE": "lts", + "ltu-Latn-ID": "ltu", + "lu-Latn-CD": "lu", + "lua-Latn-CD": "lua", + "luc-Latn-UG": "luc", + "lud-Latn-RU": "lud", + "lue-Latn-ZM": "lue", + "luf-Latn-PG": "luf", + "lui-Latn-US": "lui", + "luj-Latn-CD": "luj", + "luk-Tibt-BT": "luk", + "lul-Latn-SS": "lul", + "lum-Latn-AO": "lum", + "lun-Latn-ZM": "lun", + "luo-Latn-KE": "luo", + "lup-Latn-GA": "lup", + "luq-Latn-CU": "luq", + "lur-Latn-ID": "lur", + "lus-Beng-BD": "lus-Beng", + "lus-Brai-IN": "lus-Brai", + "lus-Latn-IN": "lus", + "lut-Latn-US": "lut", + "luu-Deva-NP": "luu", + "luv-Arab-OM": "luv", + "luw-Latn-CM": "luw", + "luy-Latn-KE": "luy", + "luz-Arab-IR": "luz", + "lv-Latn-LV": "lv", + "lva-Latn-TL": "lva", + "lvi-Latn-LA": "lvi", + "lvk-Latn-SB": "lvk", + "lvu-Latn-ID": "lvu", + "lwa-Latn-CD": "lwa", + "lwe-Latn-ID": "lwe", + "lwg-Latn-KE": "lwg", + "lwh-Latn-VN": "lwh", + "lwl-Thai-TH": "lwl", + "lwm-Thai-CN": "lwm", + "lwo-Latn-SS": "lwo", + "lwo-Latn-ZA": "lwo-ZA", + "lwt-Latn-ID": "lwt", + "lww-Latn-VU": "lww", + "lxm-Latn-PG": "lxm", + "lya-Tibt-BT": "lya", + "lyn-Latn-ZM": "lyn", + "lzh-Hans-CN": "lzh", + "lzh-Phag-CN": "lzh-Phag", + "lzl-Latn-VU": "lzl", + "lzn-Latn-MM": "lzn", + "lzz-Latn-TR": "lzz", + "maa-Latn-MX": "maa", + "mab-Latn-MX": "mab", + "mad-Latn-ID": "mad", + "mae-Latn-NG": "mae", + "maf-Latn-CM": "maf", + "mag-Deva-IN": "mag", + "mai-Deva-IN": "mai", + "mai-Tirh-IN": "mai-Tirh", + "maj-Latn-MX": "maj", + "mak-Latn-ID": "mak", + "mak-Maka-ID": "mak-Maka", + "mam-Latn-GT": "mam", + "man-Latn-GM": "man", + "man-Nkoo-GN": "man-GN", + "maq-Latn-MX": "maq", + "mas-Latn-KE": "mas", + "mat-Latn-MX": "mat", + "mau-Latn-MX": "mau", + "mav-Latn-BR": "mav", + "maw-Latn-ZZ": "maw", + "max-Latn-ID": "max", + "maz-Latn-MX": "maz", + "mba-Latn-PH": "mba", + "mbb-Latn-PH": "mbb", + "mbc-Latn-BR": "mbc", + "mbd-Latn-PH": "mbd", + "mbf-Latn-SG": "mbf", + "mbh-Latn-ZZ": "mbh", + "mbi-Latn-PH": "mbi", + "mbj-Latn-BR": "mbj", + "mbk-Latn-PG": "mbk", + "mbl-Latn-BR": "mbl", + "mbm-Latn-CG": "mbm", + "mbn-Latn-CO": "mbn", + "mbo-Latn-ZZ": "mbo", + "mbp-Latn-CO": "mbp", + "mbq-Latn-ZZ": "mbq", + "mbr-Latn-CO": "mbr", + "mbs-Latn-PH": "mbs", + "mbt-Latn-PH": "mbt", + "mbu-Latn-ZZ": "mbu", + "mbv-Latn-GN": "mbv", + "mbw-Latn-ZZ": "mbw", + "mbx-Latn-PG": "mbx", + "mby-Arab-PK": "mby", + "mbz-Latn-MX": "mbz", + "mca-Latn-PY": "mca", + "mcb-Latn-PE": "mcb", + "mcc-Latn-PG": "mcc", + "mcd-Latn-PE": "mcd", + "mce-Latn-MX": "mce", + "mcf-Latn-PE": "mcf", + "mcg-Latn-VE": "mcg", + "mch-Latn-VE": "mch", + "mci-Latn-ZZ": "mci", + "mcj-Latn-NG": "mcj", + "mck-Latn-AO": "mck", + "mcl-Latn-CO": "mcl", + "mcm-Latn-MY": "mcm", + "mcn-Latn-TD": "mcn", + "mco-Latn-MX": "mco", + "mcp-Latn-ZZ": "mcp", + "mcq-Latn-ZZ": "mcq", + "mcr-Latn-ZZ": "mcr", + "mcs-Latn-CM": "mcs", + "mct-Latn-CM": "mct", + "mcu-Latn-ZZ": "mcu", + "mcv-Latn-PG": "mcv", + "mcw-Latn-TD": "mcw", + "mcx-Latn-CF": "mcx", + "mcy-Latn-PG": "mcy", + "mcz-Latn-PG": "mcz", + "mda-Latn-ZZ": "mda", + "mdb-Latn-PG": "mdb", + "mdc-Latn-PG": "mdc", + "mdd-Latn-CM": "mdd", + "mde-Arab-ZZ": "mde", + "mdf-Cyrl-RU": "mdf", + "mdg-Latn-TD": "mdg", + "mdh-Latn-PH": "mdh", + "mdi-Latn-CD": "mdi", + "mdj-Latn-ZZ": "mdj", + "mdk-Latn-CD": "mdk", + "mdm-Latn-CD": "mdm", + "mdn-Latn-CF": "mdn", + "mdp-Latn-CD": "mdp", + "mdq-Latn-CD": "mdq", + "mdr-Latn-ID": "mdr", + "mds-Latn-PG": "mds", + "mdt-Latn-CG": "mdt", + "mdu-Latn-CG": "mdu", + "mdv-Latn-MX": "mdv", + "mdw-Latn-CG": "mdw", + "mdx-Ethi-ZZ": "mdx", + "mdy-Ethi-ET": "mdy", + "mdy-Latn-ET": "mdy-Latn", + "mdz-Latn-BR": "mdz", + "mea-Latn-CM": "mea", + "meb-Latn-PG": "meb", + "mec-Latn-AU": "mec", + "med-Latn-ZZ": "med", + "mee-Latn-ZZ": "mee", + "meh-Latn-MX": "meh", + "mej-Latn-ID": "mej", + "mek-Latn-ZZ": "mek", + "mel-Latn-MY": "mel", + "mem-Latn-AU": "mem", + "men-Latn-SL": "men", + "men-Mend-SL": "men-Mend", + "meo-Arab-MY": "meo-Arab", + "meo-Latn-MY": "meo", + "mep-Latn-AU": "mep", + "meq-Latn-CM": "meq", + "mer-Latn-KE": "mer", + "mes-Latn-TD": "mes", + "met-Latn-ZZ": "met", + "meu-Latn-ZZ": "meu", + "mev-Latn-LR": "mev", + "mew-Latn-NG": "mew", + "mey-Arab-MR": "mey-Arab", + "mey-Latn-MR": "mey", + "mez-Latn-US": "mez", + "mfa-Arab-TH": "mfa", + "mfb-Latn-ID": "mfb", + "mfc-Latn-CD": "mfc", + "mfd-Latn-CM": "mfd", + "mfe-Latn-MU": "mfe", + "mff-Latn-CM": "mff", + "mfg-Arab-GN": "mfg-Arab", + "mfg-Latn-GN": "mfg", + "mfh-Latn-CM": "mfh", + "mfi-Arab-CM": "mfi", + "mfi-Latn-CM": "mfi-Latn", + "mfj-Latn-CM": "mfj", + "mfk-Latn-CM": "mfk", + "mfl-Latn-NG": "mfl", + "mfm-Latn-NG": "mfm", + "mfn-Latn-ZZ": "mfn", + "mfo-Latn-ZZ": "mfo", + "mfp-Latn-ID": "mfp", + "mfq-Latn-ZZ": "mfq", + "mfr-Latn-AU": "mfr", + "mft-Latn-PG": "mft", + "mfu-Latn-AO": "mfu", + "mfv-Latn-GW": "mfv", + "mfw-Latn-PG": "mfw", + "mfx-Ethi-ET": "mfx-Ethi", + "mfx-Latn-ET": "mfx", + "mfy-Latn-MX": "mfy", + "mfz-Latn-SS": "mfz", + "mg-Latn-MG": "mg", + "mgb-Latn-TD": "mgb", + "mgc-Latn-SS": "mgc", + "mgd-Arab-SS": "mgd-Arab", + "mgd-Latn-SS": "mgd", + "mge-Latn-TD": "mge", + "mgf-Latn-ID": "mgf", + "mgg-Latn-CM": "mgg", + "mgh-Latn-MZ": "mgh", + "mgi-Latn-NG": "mgi", + "mgj-Latn-NG": "mgj", + "mgk-Latn-ID": "mgk", + "mgl-Latn-ZZ": "mgl", + "mgm-Latn-TL": "mgm", + "mgn-Latn-CF": "mgn", + "mgo-Latn-CM": "mgo", + "mgp-Deva-NP": "mgp", + "mgq-Latn-TZ": "mgq", + "mgr-Latn-ZM": "mgr", + "mgs-Latn-TZ": "mgs", + "mgt-Latn-PG": "mgt", + "mgu-Latn-PG": "mgu", + "mgv-Latn-TZ": "mgv", + "mgw-Latn-TZ": "mgw", + "mgy-Latn-TZ": "mgy", + "mgz-Latn-TZ": "mgz", + "mh-Latn-MH": "mh", + "mhb-Latn-GA": "mhb", + "mhc-Latn-MX": "mhc", + "mhd-Latn-TZ": "mhd", + "mhe-Latn-MY": "mhe", + "mhf-Latn-PG": "mhf", + "mhg-Latn-AU": "mhg", + "mhi-Latn-ZZ": "mhi", + "mhj-Arab-AF": "mhj", + "mhk-Latn-CM": "mhk", + "mhl-Latn-ZZ": "mhl", + "mhm-Latn-MZ": "mhm", + "mhn-Latn-IT": "mhn", + "mho-Latn-ZM": "mho", + "mhp-Latn-ID": "mhp", + "mhq-Latn-US": "mhq", + "mhs-Latn-ID": "mhs", + "mht-Latn-VE": "mht", + "mhu-Latn-IN": "mhu", + "mhw-Latn-BW": "mhw", + "mhx-Latn-MM": "mhx", + "mhy-Latn-ID": "mhy", + "mhz-Latn-ID": "mhz", + "mi-Latn-NZ": "mi", + "mia-Latn-US": "mia", + "mib-Latn-MX": "mib", + "mic-Latn-CA": "mic", + "mid-Mand-IQ": "mid", + "mie-Latn-MX": "mie", + "mif-Latn-ZZ": "mif", + "mig-Latn-MX": "mig", + "mih-Latn-MX": "mih", + "mii-Latn-MX": "mii", + "mij-Latn-CM": "mij", + "mik-Latn-US": "mik", + "mil-Latn-MX": "mil", + "mim-Latn-MX": "mim", + "min-Latn-ID": "min", + "mio-Latn-MX": "mio", + "mip-Latn-MX": "mip", + "miq-Latn-NI": "miq", + "mir-Latn-MX": "mir", + "mit-Latn-MX": "mit", + "miu-Latn-MX": "miu", + "miw-Latn-ZZ": "miw", + "mix-Latn-MX": "mix", + "miy-Latn-MX": "miy", + "miz-Latn-MX": "miz", + "mjb-Latn-TL": "mjb", + "mjc-Latn-MX": "mjc", + "mjd-Latn-US": "mjd", + "mje-Latn-TD": "mje", + "mjg-Latn-CN": "mjg", + "mjh-Latn-TZ": "mjh", + "mji-Latn-CN": "mji", + "mjj-Latn-PG": "mjj", + "mjk-Latn-PG": "mjk", + "mjl-Deva-IN": "mjl", + "mjl-Takr-IN": "mjl-Takr", + "mjm-Latn-PG": "mjm", + "mjn-Latn-PG": "mjn", + "mjq-Mlym-IN": "mjq", + "mjr-Mlym-IN": "mjr", + "mjs-Latn-NG": "mjs", + "mjt-Beng-BD": "mjt-Beng", + "mjt-Deva-IN": "mjt", + "mju-Telu-IN": "mju", + "mjv-Mlym-IN": "mjv", + "mjw-Latn-IN": "mjw", + "mjx-Beng-BD": "mjx-Beng", + "mjx-Latn-BD": "mjx", + "mjy-Latn-US": "mjy", + "mjz-Deva-NP": "mjz", + "mk-Cyrl-AL": "mk-AL", + "mk-Cyrl-GR": "mk-GR", + "mk-Cyrl-MK": "mk", + "mka-Latn-CI": "mka", + "mkb-Deva-IN": "mkb", + "mkc-Latn-PG": "mkc", + "mke-Deva-IN": "mke", + "mkf-Latn-NG": "mkf", + "mki-Arab-ZZ": "mki", + "mkj-Latn-FM": "mkj", + "mkk-Latn-CM": "mkk", + "mkl-Latn-ZZ": "mkl", + "mkm-Thai-TH": "mkm", + "mkn-Latn-ID": "mkn", + "mko-Latn-NG": "mko", + "mkp-Latn-ZZ": "mkp", + "mkr-Latn-PG": "mkr", + "mks-Latn-MX": "mks", + "mkt-Latn-NC": "mkt", + "mku-Latn-GN": "mku", + "mkv-Latn-VU": "mkv", + "mkw-Latn-ZZ": "mkw", + "mkx-Latn-PH": "mkx", + "mky-Latn-ID": "mky", + "mkz-Latn-TL": "mkz", + "ml-Mlym-IN": "ml", + "mla-Latn-VU": "mla", + "mlb-Latn-CM": "mlb", + "mlc-Latn-VN": "mlc", + "mle-Latn-ZZ": "mle", + "mlf-Latn-LA": "mlf-Latn", + "mlf-Thai-LA": "mlf", + "mlh-Latn-PG": "mlh", + "mli-Latn-ID": "mli", + "mlj-Latn-TD": "mlj", + "mlk-Latn-KE": "mlk", + "mll-Latn-VU": "mll", + "mln-Latn-SB": "mln", + "mlo-Latn-SN": "mlo", + "mlp-Latn-ZZ": "mlp", + "mlq-Arab-SN": "mlq-Arab", + "mlq-Latn-SN": "mlq", + "mlr-Latn-CM": "mlr", + "mls-Latn-SD": "mls", + "mlu-Latn-SB": "mlu", + "mlv-Latn-VU": "mlv", + "mlw-Latn-CM": "mlw", + "mlx-Latn-VU": "mlx", + "mlz-Latn-PH": "mlz", + "mma-Latn-NG": "mma", + "mmb-Latn-ID": "mmb", + "mmc-Latn-MX": "mmc", + "mmd-Hans-CN": "mmd-Hans", + "mmd-Hant-CN": "mmd-Hant", + "mmd-Latn-CN": "mmd", + "mme-Latn-VU": "mme", + "mmf-Latn-NG": "mmf", + "mmg-Latn-VU": "mmg", + "mmh-Latn-BR": "mmh", + "mmi-Latn-PG": "mmi", + "mmm-Latn-VU": "mmm", + "mmn-Latn-PH": "mmn", + "mmo-Latn-ZZ": "mmo", + "mmp-Latn-PG": "mmp", + "mmq-Latn-PG": "mmq", + "mmr-Latn-CN": "mmr", + "mmt-Latn-PG": "mmt", + "mmu-Latn-ZZ": "mmu", + "mmv-Latn-BR": "mmv", + "mmw-Latn-VU": "mmw", + "mmx-Latn-ZZ": "mmx", + "mmy-Latn-TD": "mmy", + "mmz-Latn-CD": "mmz", + "mn-Cyrl-MN": "mn", + "mn-Mong-CN": "mn-CN", + "mna-Latn-ZZ": "mna", + "mnb-Latn-ID": "mnb", + "mnd-Latn-BR": "mnd", + "mne-Latn-TD": "mne", + "mnf-Latn-ZZ": "mnf", + "mng-Latn-VN": "mng", + "mnh-Latn-CD": "mnh", + "mni-Beng-IN": "mni", + "mni-Mtei-IN": "mni-Mtei", + "mnj-Arab-AF": "mnj", + "mnl-Latn-VU": "mnl", + "mnm-Latn-PG": "mnm", + "mnn-Latn-VN": "mnn", + "mnp-Latn-CN": "mnp", + "mnq-Latn-MY": "mnq", + "mnr-Latn-US": "mnr", + "mns-Cyrl-RU": "mns", + "mnu-Latn-ID": "mnu", + "mnv-Latn-SB": "mnv", + "mnw-Mymr-MM": "mnw", + "mnw-Mymr-TH": "mnw-TH", + "mnx-Latn-ID": "mnx", + "mny-Latn-MZ": "mny", + "mnz-Latn-ID": "mnz", + "moa-Latn-ZZ": "moa", + "moc-Latn-AR": "moc", + "mod-Latn-US": "mod", + "moe-Latn-CA": "moe", + "mog-Latn-ID": "mog", + "moh-Latn-CA": "moh", + "moi-Latn-NG": "moi", + "moj-Latn-CG": "moj", + "mok-Latn-ID": "mok", + "mom-Latn-NI": "mom", + "moo-Latn-VN": "moo", + "mop-Latn-BZ": "mop", + "moq-Latn-ID": "moq", + "mor-Latn-SD": "mor", + "mos-Latn-BF": "mos", + "mot-Latn-CO": "mot", + "mou-Latn-TD": "mou", + "mov-Latn-US": "mov", + "mow-Latn-CG": "mow", + "mox-Latn-ZZ": "mox", + "moy-Ethi-ET": "moy-Ethi", + "moy-Latn-ET": "moy", + "moz-Latn-TD": "moz", + "mpa-Latn-TZ": "mpa", + "mpb-Latn-AU": "mpb", + "mpc-Latn-AU": "mpc", + "mpd-Latn-BR": "mpd", + "mpe-Ethi-ET": "mpe-Ethi", + "mpe-Latn-ET": "mpe", + "mpg-Latn-TD": "mpg", + "mph-Latn-AU": "mph", + "mpi-Latn-CM": "mpi", + "mpj-Latn-AU": "mpj", + "mpk-Latn-TD": "mpk", + "mpl-Latn-PG": "mpl", + "mpm-Latn-MX": "mpm", + "mpn-Latn-PG": "mpn", + "mpo-Latn-PG": "mpo", + "mpp-Latn-ZZ": "mpp", + "mpq-Latn-BR": "mpq", + "mpr-Latn-SB": "mpr", + "mps-Latn-ZZ": "mps", + "mpt-Latn-ZZ": "mpt", + "mpu-Latn-BR": "mpu", + "mpv-Latn-PG": "mpv", + "mpw-Latn-BR": "mpw", + "mpx-Latn-ZZ": "mpx", + "mpy-Latn-ID": "mpy", + "mpz-Thai-TH": "mpz", + "mqa-Latn-ID": "mqa", + "mqb-Latn-CM": "mqb", + "mqc-Latn-ID": "mqc", + "mqe-Latn-PG": "mqe", + "mqf-Latn-ID": "mqf", + "mqg-Latn-ID": "mqg", + "mqh-Latn-MX": "mqh", + "mqi-Latn-ID": "mqi", + "mqj-Latn-ID": "mqj", + "mqk-Latn-PH": "mqk", + "mql-Latn-ZZ": "mql", + "mqm-Latn-PF": "mqm", + "mqn-Latn-ID": "mqn", + "mqo-Latn-ID": "mqo", + "mqp-Latn-ID": "mqp", + "mqq-Latn-MY": "mqq", + "mqr-Latn-ID": "mqr", + "mqs-Latn-ID": "mqs", + "mqu-Latn-SS": "mqu", + "mqv-Latn-PG": "mqv", + "mqw-Latn-PG": "mqw", + "mqx-Bugi-ID": "mqx-Bugi", + "mqx-Latn-ID": "mqx", + "mqy-Latn-ID": "mqy", + "mqz-Latn-PG": "mqz", + "mr-Deva-IN": "mr", + "mr-Modi-IN": "mr-Modi", + "mra-Thai-TH": "mra", + "mrb-Latn-VU": "mrb", + "mrc-Latn-US": "mrc", + "mrd-Deva-NP": "mrd", + "mrf-Latn-ID": "mrf", + "mrg-Beng-IN": "mrg-Beng", + "mrg-Deva-IN": "mrg-Deva", + "mrg-Latn-IN": "mrg", + "mrh-Latn-IN": "mrh", + "mrj-Cyrl-RU": "mrj", + "mrk-Latn-NC": "mrk", + "mrl-Latn-FM": "mrl", + "mrm-Latn-VU": "mrm", + "mrn-Latn-SB": "mrn", + "mro-Mroo-BD": "mro", + "mrp-Latn-VU": "mrp", + "mrq-Latn-PF": "mrq", + "mrr-Deva-IN": "mrr", + "mrs-Latn-VU": "mrs", + "mrt-Latn-NG": "mrt", + "mru-Latn-CM": "mru", + "mrv-Latn-PF": "mrv", + "mrw-Arab-PH": "mrw-Arab", + "mrw-Latn-PH": "mrw", + "mrx-Latn-ID": "mrx", + "mry-Latn-PH": "mry", + "mrz-Latn-ID": "mrz", + "ms-Arab-CC": "ms-CC", + "ms-Arab-ID": "ms-Arab-ID", + "ms-Latn-BN": "ms-BN", + "ms-Latn-MY": "ms", + "msb-Latn-PH": "msb", + "msc-Latn-GN": "msc", + "mse-Latn-TD": "mse", + "msf-Latn-ID": "msf", + "msg-Latn-ID": "msg", + "msh-Latn-MG": "msh", + "msi-Latn-MY": "msi", + "msj-Latn-CD": "msj", + "msk-Latn-PH": "msk", + "msl-Latn-ID": "msl", + "msm-Latn-PH": "msm", + "msn-Latn-VU": "msn", + "mso-Latn-ID": "mso", + "msp-Latn-BR": "msp", + "msq-Latn-NC": "msq", + "mss-Latn-ID": "mss", + "msu-Latn-PG": "msu", + "msv-Latn-CM": "msv", + "msw-Latn-GW": "msw", + "msx-Latn-PG": "msx", + "msy-Latn-PG": "msy", + "msz-Latn-PG": "msz", + "mt-Latn-MT": "mt", + "mta-Latn-PH": "mta", + "mtb-Latn-CI": "mtb", + "mtc-Latn-ZZ": "mtc", + "mtd-Latn-ID": "mtd", + "mte-Latn-SB": "mte", + "mtf-Latn-ZZ": "mtf", + "mtg-Latn-ID": "mtg", + "mth-Latn-ID": "mth", + "mti-Latn-ZZ": "mti", + "mtj-Latn-ID": "mtj", + "mtk-Latn-CM": "mtk", + "mtl-Latn-NG": "mtl", + "mtm-Cyrl-RU": "mtm", + "mtn-Latn-NI": "mtn", + "mto-Latn-MX": "mto", + "mtp-Latn-BO": "mtp", + "mtq-Latn-VN": "mtq", + "mtr-Deva-IN": "mtr", + "mts-Latn-PE": "mts", + "mtt-Latn-VU": "mtt", + "mtu-Latn-MX": "mtu", + "mtv-Latn-PG": "mtv", + "mtw-Latn-PH": "mtw", + "mtx-Latn-MX": "mtx", + "mty-Latn-PG": "mty", + "mua-Latn-CM": "mua", + "mub-Latn-TD": "mub", + "muc-Latn-CM": "muc", + "mud-Cyrl-RU": "mud", + "mue-Latn-EC": "mue", + "mug-Latn-CM": "mug", + "muh-Latn-SS": "muh", + "mui-Latn-ID": "mui", + "muj-Latn-TD": "muj", + "muk-Tibt-NP": "muk", + "mum-Latn-PG": "mum", + "muo-Latn-CM": "muo", + "muq-Latn-CN": "muq", + "mur-Latn-ZZ": "mur", + "mus-Latn-US": "mus", + "mut-Deva-IN": "mut", + "muu-Latn-KE": "muu", + "muv-Taml-IN": "muv", + "mux-Latn-PG": "mux", + "muy-Latn-CM": "muy", + "muz-Ethi-ET": "muz", + "muz-Latn-ET": "muz-Latn", + "mva-Latn-ZZ": "mva", + "mvd-Latn-ID": "mvd", + "mvf-Mong-CN": "mvf", + "mvf-Phag-CN": "mvf-Phag", + "mvg-Latn-MX": "mvg", + "mvh-Latn-TD": "mvh", + "mvk-Latn-PG": "mvk", + "mvl-Latn-AU": "mvl", + "mvn-Latn-ZZ": "mvn", + "mvo-Latn-SB": "mvo", + "mvp-Latn-ID": "mvp", + "mvq-Latn-PG": "mvq", + "mvr-Latn-ID": "mvr", + "mvs-Latn-ID": "mvs", + "mvt-Latn-VU": "mvt", + "mvu-Latn-TD": "mvu", + "mvv-Latn-MY": "mvv", + "mvw-Latn-TZ": "mvw", + "mvx-Latn-ID": "mvx", + "mvy-Arab-PK": "mvy", + "mvz-Arab-ET": "mvz-Arab", + "mvz-Ethi-ET": "mvz", + "mwa-Latn-PG": "mwa", + "mwb-Latn-PG": "mwb", + "mwc-Latn-PG": "mwc", + "mwe-Latn-TZ": "mwe", + "mwf-Latn-AU": "mwf", + "mwg-Latn-PG": "mwg", + "mwh-Latn-PG": "mwh", + "mwi-Latn-VU": "mwi", + "mwk-Latn-ML": "mwk", + "mwl-Latn-PT": "mwl", + "mwm-Latn-TD": "mwm", + "mwn-Latn-ZM": "mwn", + "mwo-Latn-VU": "mwo", + "mwp-Latn-AU": "mwp", + "mwq-Latn-MM": "mwq", + "mwr-Deva-IN": "mwr", + "mws-Latn-KE": "mws", + "mwt-Mymr-MM": "mwt", + "mwt-Thai-TH": "mwt-Thai", + "mwu-Latn-SS": "mwu", + "mwv-Latn-ID": "mwv", + "mww-Hmnp-US": "mww", + "mwz-Latn-CD": "mwz", + "mxa-Latn-MX": "mxa", + "mxb-Latn-MX": "mxb", + "mxc-Latn-ZW": "mxc", + "mxd-Latn-ID": "mxd", + "mxe-Latn-VU": "mxe", + "mxf-Latn-CM": "mxf", + "mxg-Latn-AO": "mxg", + "mxh-Latn-CD": "mxh", + "mxi-Latn-ES": "mxi", + "mxj-Latn-IN": "mxj", + "mxk-Latn-PG": "mxk", + "mxl-Latn-BJ": "mxl", + "mxm-Latn-ZZ": "mxm", + "mxn-Latn-ID": "mxn", + "mxo-Latn-ZM": "mxo", + "mxp-Latn-MX": "mxp", + "mxq-Latn-MX": "mxq", + "mxr-Latn-MY": "mxr", + "mxs-Latn-MX": "mxs", + "mxt-Latn-MX": "mxt", + "mxu-Latn-CM": "mxu", + "mxv-Latn-MX": "mxv", + "mxw-Latn-PG": "mxw", + "mxx-Latn-CI": "mxx", + "mxy-Latn-MX": "mxy", + "mxz-Latn-ID": "mxz", + "my-Mymr-MM": "my", + "myb-Latn-TD": "myb", + "myc-Latn-CD": "myc", + "mye-Latn-GA": "mye", + "myf-Latn-ET": "myf", + "myg-Latn-CM": "myg", + "myh-Latn-US": "myh", + "myj-Latn-SS": "myj", + "myk-Latn-ZZ": "myk", + "myl-Latn-ID": "myl", + "mym-Ethi-ZZ": "mym", + "myp-Latn-BR": "myp", + "myr-Latn-PE": "myr", + "myu-Latn-BR": "myu", + "myv-Cyrl-RU": "myv", + "myw-Latn-ZZ": "myw", + "myx-Latn-UG": "myx", + "myy-Latn-CO": "myy", + "myz-Mand-IR": "myz", + "mza-Latn-MX": "mza", + "mzd-Latn-CM": "mzd", + "mze-Latn-PG": "mze", + "mzh-Latn-AR": "mzh", + "mzi-Latn-MX": "mzi", + "mzj-Latn-LR": "mzj", + "mzk-Latn-ZZ": "mzk", + "mzl-Latn-MX": "mzl", + "mzm-Latn-ZZ": "mzm", + "mzn-Arab-IR": "mzn", + "mzo-Latn-BR": "mzo", + "mzp-Latn-ZZ": "mzp", + "mzq-Latn-ID": "mzq", + "mzr-Latn-BR": "mzr", + "mzt-Latn-MY": "mzt", + "mzu-Latn-PG": "mzu", + "mzv-Latn-CF": "mzv", + "mzw-Latn-ZZ": "mzw", + "mzx-Latn-GY": "mzx", + "mzz-Latn-ZZ": "mzz", + "na-Latn-NR": "na", + "naa-Latn-ID": "naa", + "nab-Latn-BR": "nab", + "nac-Latn-ZZ": "nac", + "nae-Latn-ID": "nae", + "naf-Latn-ZZ": "naf", + "nag-Latn-IN": "nag", + "naj-Latn-GN": "naj", + "nak-Latn-ZZ": "nak", + "nal-Latn-PG": "nal", + "nam-Latn-AU": "nam", + "nan-Hans-CN": "nan", + "nao-Deva-NP": "nao", + "nap-Latn-IT": "nap", + "naq-Latn-NA": "naq", + "nar-Latn-NG": "nar", + "nas-Latn-ZZ": "nas", + "nat-Latn-NG": "nat", + "naw-Latn-GH": "naw", + "nax-Latn-PG": "nax", + "nay-Latn-AU": "nay", + "naz-Latn-MX": "naz", + "nb-Latn-NO": "nb", + "nb-Latn-SJ": "nb-SJ", + "nba-Latn-AO": "nba", + "nbb-Latn-NG": "nbb", + "nbc-Latn-IN": "nbc", + "nbd-Latn-CD": "nbd", + "nbe-Latn-IN": "nbe", + "nbh-Latn-NG": "nbh", + "nbi-Latn-IN": "nbi", + "nbj-Latn-AU": "nbj", + "nbk-Latn-PG": "nbk", + "nbm-Latn-CF": "nbm", + "nbn-Latn-ID": "nbn", + "nbo-Latn-NG": "nbo", + "nbp-Latn-NG": "nbp", + "nbq-Latn-ID": "nbq", + "nbr-Latn-NG": "nbr", + "nbt-Deva-IN": "nbt-Deva", + "nbt-Latn-IN": "nbt", + "nbu-Latn-IN": "nbu", + "nbv-Latn-CM": "nbv", + "nbw-Latn-CD": "nbw", + "nby-Latn-PG": "nby", + "nca-Latn-ZZ": "nca", + "ncb-Deva-IN": "ncb-Deva", + "ncb-Latn-IN": "ncb", + "ncc-Latn-PG": "ncc", + "ncd-Deva-NP": "ncd", + "nce-Latn-ZZ": "nce", + "ncf-Latn-ZZ": "ncf", + "ncg-Latn-CA": "ncg", + "nch-Latn-MX": "nch", + "nci-Latn-MX": "nci", + "ncj-Latn-MX": "ncj", + "nck-Latn-AU": "nck", + "ncl-Latn-MX": "ncl", + "ncm-Latn-PG": "ncm", + "ncn-Latn-PG": "ncn", + "nco-Latn-ZZ": "nco", + "ncq-Laoo-LA": "ncq", + "ncq-Thai-LA": "ncq-Thai", + "ncr-Latn-CM": "ncr", + "nct-Beng-IN": "nct-Beng", + "nct-Latn-IN": "nct", + "ncu-Latn-ZZ": "ncu", + "ncx-Latn-MX": "ncx", + "ncz-Latn-US": "ncz", + "nd-Latn-ZW": "nd", + "nda-Latn-CG": "nda", + "ndb-Latn-CM": "ndb", + "ndc-Latn-MZ": "ndc", + "ndd-Latn-NG": "ndd", + "ndf-Cyrl-RU": "ndf", + "ndg-Latn-TZ": "ndg", + "ndh-Latn-TZ": "ndh", + "ndi-Latn-NG": "ndi", + "ndj-Latn-TZ": "ndj", + "ndk-Latn-CD": "ndk", + "ndl-Latn-CD": "ndl", + "ndm-Latn-TD": "ndm", + "ndn-Latn-CG": "ndn", + "ndp-Latn-UG": "ndp", + "ndq-Latn-AO": "ndq", + "ndr-Latn-NG": "ndr", + "nds-Latn-DE": "nds", + "ndt-Latn-CD": "ndt", + "ndu-Latn-CM": "ndu", + "ndv-Latn-SN": "ndv", + "ndw-Latn-CD": "ndw", + "ndx-Latn-ID": "ndx", + "ndy-Latn-CF": "ndy", + "ndy-Latn-TD": "ndy-TD", + "ndz-Latn-SS": "ndz", + "ne-Deva-BT": "ne-BT", + "ne-Deva-NP": "ne", + "nea-Latn-ID": "nea", + "neb-Latn-ZZ": "neb", + "nec-Latn-ID": "nec", + "ned-Latn-NG": "ned", + "nee-Latn-NC": "nee", + "neg-Cyrl-RU": "neg", + "neh-Tibt-BT": "neh", + "nei-Xsux-TR": "nei", + "nej-Latn-PG": "nej", + "nek-Latn-NC": "nek", + "nem-Latn-NC": "nem", + "nen-Latn-NC": "nen", + "neo-Latn-VN": "neo", + "neq-Latn-MX": "neq", + "ner-Latn-ID": "ner", + "net-Latn-PG": "net", + "neu-Latn-001": "neu", + "new-Deva-NP": "new", + "new-Newa-NP": "new-Newa", + "nex-Latn-ZZ": "nex", + "ney-Latn-CI": "ney", + "nez-Latn-US": "nez", + "nfa-Latn-ID": "nfa", + "nfd-Latn-NG": "nfd", + "nfl-Latn-SB": "nfl", + "nfr-Latn-ZZ": "nfr", + "nfu-Latn-CM": "nfu", + "ng-Latn-NA": "ng", + "nga-Latn-ZZ": "nga", + "ngb-Latn-ZZ": "ngb", + "ngc-Latn-CD": "ngc", + "ngd-Latn-CF": "ngd", + "nge-Latn-CM": "nge", + "ngg-Latn-CF": "ngg", + "ngh-Latn-ZA": "ngh", + "ngi-Latn-NG": "ngi", + "ngj-Latn-CM": "ngj", + "ngk-Latn-AU": "ngk", + "ngl-Latn-MZ": "ngl", + "ngm-Latn-FM": "ngm", + "ngn-Latn-CM": "ngn", + "ngp-Latn-TZ": "ngp", + "ngq-Latn-TZ": "ngq", + "ngr-Latn-SB": "ngr", + "ngs-Latn-NG": "ngs", + "ngt-Laoo-LA": "ngt", + "ngu-Latn-MX": "ngu", + "ngv-Latn-CM": "ngv", + "ngw-Latn-NG": "ngw", + "ngx-Latn-NG": "ngx", + "ngy-Latn-CM": "ngy", + "ngz-Latn-CG": "ngz", + "nha-Latn-AU": "nha", + "nhb-Latn-ZZ": "nhb", + "nhc-Latn-MX": "nhc", + "nhd-Latn-PY": "nhd", + "nhe-Latn-MX": "nhe", + "nhf-Latn-AU": "nhf", + "nhg-Latn-MX": "nhg", + "nhi-Latn-MX": "nhi", + "nhk-Latn-MX": "nhk", + "nhm-Latn-MX": "nhm", + "nhn-Latn-MX": "nhn", + "nho-Latn-PG": "nho", + "nhp-Latn-MX": "nhp", + "nhq-Latn-MX": "nhq", + "nhr-Latn-BW": "nhr", + "nht-Latn-MX": "nht", + "nhu-Latn-CM": "nhu", + "nhv-Latn-MX": "nhv", + "nhw-Latn-MX": "nhw", + "nhx-Latn-MX": "nhx", + "nhy-Latn-MX": "nhy", + "nhz-Latn-MX": "nhz", + "nia-Latn-ID": "nia", + "nib-Latn-PG": "nib", + "nid-Latn-AU": "nid", + "nie-Latn-TD": "nie", + "nif-Latn-ZZ": "nif", + "nig-Latn-AU": "nig", + "nih-Latn-TZ": "nih", + "nii-Latn-ZZ": "nii", + "nij-Latn-ID": "nij", + "nil-Latn-ID": "nil", + "nim-Latn-TZ": "nim", + "nin-Latn-ZZ": "nin", + "nio-Cyrl-RU": "nio", + "niq-Latn-KE": "niq", + "nir-Latn-ID": "nir", + "nis-Latn-PG": "nis", + "nit-Telu-IN": "nit", + "niu-Latn-NU": "niu", + "niv-Cyrl-RU": "niv", + "niv-Latn-RU": "niv-Latn", + "niw-Latn-PG": "niw", + "nix-Latn-CD": "nix", + "niy-Latn-ZZ": "niy", + "niz-Latn-ZZ": "niz", + "nja-Latn-NG": "nja", + "njb-Latn-IN": "njb", + "njd-Latn-TZ": "njd", + "njh-Latn-IN": "njh", + "nji-Latn-AU": "nji", + "njj-Latn-CM": "njj", + "njl-Latn-SS": "njl", + "njm-Latn-IN": "njm", + "njn-Latn-IN": "njn", + "njo-Latn-IN": "njo", + "njr-Latn-NG": "njr", + "njs-Latn-ID": "njs", + "njt-Latn-SR": "njt", + "nju-Latn-AU": "nju", + "njx-Latn-CG": "njx", + "njy-Latn-CM": "njy", + "njz-Beng-IN": "njz-Beng", + "njz-Latn-IN": "njz", + "nka-Latn-ZM": "nka", + "nkb-Latn-IN": "nkb", + "nkc-Latn-CM": "nkc", + "nkd-Latn-IN": "nkd", + "nke-Latn-SB": "nke", + "nkf-Latn-IN": "nkf", + "nkg-Latn-ZZ": "nkg", + "nkh-Latn-IN": "nkh", + "nki-Beng-IN": "nki-Beng", + "nki-Latn-IN": "nki", + "nkj-Latn-ID": "nkj", + "nkk-Latn-VU": "nkk", + "nkm-Latn-PG": "nkm", + "nkn-Latn-AO": "nkn", + "nko-Latn-ZZ": "nko", + "nkq-Latn-GH": "nkq", + "nkr-Latn-FM": "nkr", + "nks-Latn-ID": "nks", + "nkt-Latn-TZ": "nkt", + "nku-Latn-CI": "nku", + "nkv-Latn-MW": "nkv", + "nkw-Latn-CD": "nkw", + "nkx-Latn-NG": "nkx", + "nkz-Latn-NG": "nkz", + "nl-Latn-AW": "nl-AW", + "nl-Latn-BE": "nl-BE", + "nl-Latn-NL": "nl", + "nl-Latn-SR": "nl-SR", + "nla-Latn-CM": "nla", + "nlc-Latn-ID": "nlc", + "nle-Latn-KE": "nle", + "nlg-Latn-SB": "nlg", + "nli-Arab-AF": "nli", + "nlj-Latn-CD": "nlj", + "nlk-Latn-ID": "nlk", + "nlm-Arab-PK": "nlm", + "nlo-Latn-CD": "nlo", + "nlq-Latn-MM": "nlq", + "nlu-Latn-GH": "nlu", + "nlv-Latn-MX": "nlv", + "nlw-Latn-AU": "nlw", + "nlx-Deva-IN": "nlx", + "nly-Latn-AU": "nly", + "nlz-Latn-SB": "nlz", + "nma-Latn-IN": "nma", + "nmb-Latn-VU": "nmb", + "nmc-Latn-TD": "nmc", + "nmd-Latn-GA": "nmd", + "nme-Latn-IN": "nme", + "nmf-Latn-IN": "nmf", + "nmg-Latn-CM": "nmg", + "nmh-Latn-IN": "nmh", + "nmi-Latn-NG": "nmi", + "nmj-Latn-CF": "nmj", + "nmk-Latn-VU": "nmk", + "nml-Latn-CM": "nml", + "nmm-Deva-NP": "nmm", + "nmm-Tibt-NP": "nmm-Tibt", + "nmn-Latn-BW": "nmn", + "nmo-Beng-IN": "nmo-Beng", + "nmo-Latn-IN": "nmo", + "nmp-Latn-AU": "nmp", + "nmq-Latn-ZW": "nmq", + "nmr-Latn-CM": "nmr", + "nms-Latn-VU": "nms", + "nmt-Latn-FM": "nmt", + "nmu-Latn-US": "nmu", + "nmv-Latn-AU": "nmv", + "nmw-Latn-PG": "nmw", + "nmx-Latn-PG": "nmx", + "nmz-Latn-ZZ": "nmz", + "nn-Latn-NO": "nn", + "nna-Latn-AU": "nna", + "nnb-Latn-CD": "nnb", + "nnc-Latn-TD": "nnc", + "nnd-Latn-VU": "nnd", + "nne-Latn-AO": "nne", + "nnf-Latn-ZZ": "nnf", + "nng-Beng-IN": "nng-Beng", + "nng-Latn-IN": "nng", + "nnh-Latn-CM": "nnh", + "nni-Latn-ID": "nni", + "nnj-Latn-ET": "nnj", + "nnk-Latn-ZZ": "nnk", + "nnl-Latn-IN": "nnl", + "nnm-Latn-ZZ": "nnm", + "nnn-Latn-TD": "nnn", + "nnp-Wcho-IN": "nnp", + "nnq-Latn-TZ": "nnq", + "nnr-Latn-AU": "nnr", + "nnt-Latn-US": "nnt", + "nnu-Latn-GH": "nnu", + "nnv-Latn-AU": "nnv", + "nnw-Latn-BF": "nnw", + "nny-Latn-AU": "nny", + "nnz-Latn-CM": "nnz", + "no-Latn-NO": "no", + "noa-Latn-CO": "noa", + "noc-Latn-PG": "noc", + "nod-Lana-TH": "nod", + "noe-Deva-IN": "noe", + "nof-Latn-PG": "nof", + "nog-Cyrl-RU": "nog", + "noh-Latn-PG": "noh", + "noi-Deva-IN": "noi", + "noj-Latn-CO": "noj", + "nok-Latn-US": "nok", + "nom-Latn-PE": "nom", + "non-Runr-SE": "non", + "nop-Latn-ZZ": "nop", + "noq-Latn-CD": "noq", + "nos-Yiii-CN": "nos", + "not-Latn-PE": "not", + "nou-Latn-ZZ": "nou", + "nov-Latn-001": "nov", + "now-Latn-TZ": "now", + "noy-Latn-TD": "noy", + "npb-Tibt-BT": "npb", + "npg-Latn-MM": "npg", + "nph-Latn-IN": "nph", + "npl-Latn-MX": "npl", + "npn-Latn-PG": "npn", + "npo-Latn-IN": "npo", + "nps-Latn-ID": "nps", + "npu-Latn-IN": "npu", + "npx-Latn-SB": "npx", + "npy-Latn-ID": "npy", + "nqg-Latn-BJ": "nqg", + "nqk-Latn-BJ": "nqk", + "nql-Latn-AO": "nql", + "nqm-Latn-ID": "nqm", + "nqn-Latn-PG": "nqn", + "nqo-Nkoo-GN": "nqo", + "nqq-Latn-MM": "nqq", + "nqt-Latn-NG": "nqt", + "nqy-Latn-MM": "nqy", + "nr-Latn-ZA": "nr", + "nra-Latn-GA": "nra", + "nrb-Latn-ZZ": "nrb", + "nre-Latn-IN": "nre", + "nrf-Latn-JE": "nrf", + "nrg-Latn-VU": "nrg", + "nri-Latn-IN": "nri", + "nrk-Latn-AU": "nrk", + "nrl-Latn-AU": "nrl", + "nrm-Latn-MY": "nrm", + "nrp-Latn-IT": "nrp", + "nru-Hans-CN": "nru-Hans", + "nru-Hant-CN": "nru-Hant", + "nru-Latn-CN": "nru", + "nrx-Latn-AU": "nrx", + "nrz-Latn-PG": "nrz", + "nsa-Latn-IN": "nsa", + "nsb-Latn-ZA": "nsb", + "nsc-Latn-NG": "nsc", + "nsd-Yiii-CN": "nsd", + "nse-Latn-ZM": "nse", + "nsf-Yiii-CN": "nsf", + "nsg-Latn-TZ": "nsg", + "nsh-Latn-CM": "nsh", + "nsk-Cans-CA": "nsk", + "nsm-Latn-IN": "nsm", + "nsn-Latn-ZZ": "nsn", + "nso-Latn-ZA": "nso", + "nsq-Latn-US": "nsq", + "nss-Latn-ZZ": "nss", + "nst-Tnsa-IN": "nst", + "nsu-Latn-MX": "nsu", + "nsv-Yiii-CN": "nsv", + "nsw-Latn-VU": "nsw", + "nsx-Latn-AO": "nsx", + "nsy-Latn-ID": "nsy", + "nsz-Latn-US": "nsz", + "ntd-Latn-MY": "ntd", + "nte-Latn-MZ": "nte", + "ntg-Latn-AU": "ntg", + "nti-Latn-BF": "nti", + "ntj-Latn-AU": "ntj", + "ntk-Latn-TZ": "ntk", + "ntm-Latn-ZZ": "ntm", + "nto-Latn-CD": "nto", + "ntp-Latn-MX": "ntp", + "ntr-Latn-ZZ": "ntr", + "ntu-Latn-SB": "ntu", + "ntx-Latn-MM": "ntx", + "nty-Yiii-VN": "nty", + "ntz-Arab-IR": "ntz", + "nua-Latn-NC": "nua", + "nuc-Latn-BR": "nuc", + "nud-Latn-PG": "nud", + "nue-Latn-CD": "nue", + "nuf-Latn-CN": "nuf", + "nug-Latn-AU": "nug", + "nuh-Latn-NG": "nuh", + "nui-Latn-ZZ": "nui", + "nuj-Latn-UG": "nuj", + "nuk-Latn-CA": "nuk", + "num-Latn-TO": "num", + "nun-Latn-MM": "nun", + "nuo-Latn-VN": "nuo", + "nup-Latn-ZZ": "nup", + "nuq-Latn-PG": "nuq", + "nur-Latn-PG": "nur", + "nus-Latn-SS": "nus", + "nut-Latn-VN": "nut", + "nuu-Latn-CD": "nuu", + "nuv-Latn-ZZ": "nuv", + "nuw-Latn-FM": "nuw", + "nux-Latn-ZZ": "nux", + "nuy-Latn-AU": "nuy", + "nuz-Latn-MX": "nuz", + "nv-Latn-US": "nv", + "nvh-Latn-VU": "nvh", + "nvm-Latn-PG": "nvm", + "nvo-Latn-CM": "nvo", + "nwb-Latn-ZZ": "nwb", + "nwc-Brah-NP": "nwc-Brah", + "nwc-Deva-NP": "nwc-Deva", + "nwc-Newa-NP": "nwc", + "nwc-Sidd-NP": "nwc-Sidd", + "nwe-Latn-CM": "nwe", + "nwg-Latn-AU": "nwg", + "nwi-Latn-VU": "nwi", + "nwm-Latn-SS": "nwm", + "nwo-Latn-AU": "nwo", + "nwr-Latn-PG": "nwr", + "nww-Latn-TZ": "nww", + "nwx-Deva-NP": "nwx", + "nxa-Latn-TL": "nxa", + "nxd-Latn-CD": "nxd", + "nxe-Latn-ID": "nxe", + "nxg-Latn-ID": "nxg", + "nxi-Latn-TZ": "nxi", + "nxl-Latn-ID": "nxl", + "nxn-Latn-AU": "nxn", + "nxo-Latn-GA": "nxo", + "nxq-Latn-CN": "nxq", + "nxr-Latn-ZZ": "nxr", + "nxx-Latn-ID": "nxx", + "ny-Latn-MW": "ny", + "nyb-Latn-GH": "nyb", + "nyc-Latn-CD": "nyc", + "nyd-Latn-KE": "nyd", + "nye-Latn-AO": "nye", + "nyf-Latn-KE": "nyf", + "nyg-Latn-CD": "nyg", + "nyh-Latn-AU": "nyh", + "nyi-Latn-SD": "nyi", + "nyj-Latn-CD": "nyj", + "nyk-Latn-AO": "nyk", + "nyl-Thai-TH": "nyl", + "nym-Latn-TZ": "nym", + "nyn-Latn-UG": "nyn", + "nyo-Latn-UG": "nyo", + "nyp-Latn-UG": "nyp", + "nyq-Arab-IR": "nyq", + "nyr-Latn-MW": "nyr", + "nys-Latn-AU": "nys", + "nyt-Latn-AU": "nyt", + "nyu-Latn-MZ": "nyu", + "nyv-Latn-AU": "nyv", + "nyx-Latn-AU": "nyx", + "nyy-Latn-TZ": "nyy", + "nza-Latn-CM": "nza", + "nzb-Latn-GA": "nzb", + "nzd-Latn-CD": "nzd", + "nzi-Latn-GH": "nzi", + "nzk-Latn-CF": "nzk", + "nzm-Latn-IN": "nzm", + "nzu-Latn-CG": "nzu", + "nzy-Latn-TD": "nzy", + "nzz-Latn-ML": "nzz", + "oaa-Cyrl-RU": "oaa", + "oac-Cyrl-RU": "oac", + "oar-Syrc-SY": "oar", + "oav-Geor-GE": "oav", + "obi-Latn-US": "obi", + "obk-Latn-PH": "obk", + "obl-Latn-CM": "obl", + "obm-Phnx-JO": "obm", + "obo-Latn-PH": "obo", + "obr-Mymr-MM": "obr", + "obt-Latn-FR": "obt", + "obu-Latn-NG": "obu", + "oc-Latn-FR": "oc", + "oca-Latn-PE": "oca", + "oco-Latn-GB": "oco", + "ocu-Latn-MX": "ocu", + "oda-Latn-NG": "oda", + "odk-Arab-PK": "odk", + "odt-Latn-NL": "odt", + "odu-Latn-NG": "odu", + "ofu-Latn-NG": "ofu", + "ogb-Latn-NG": "ogb", + "ogc-Latn-ZZ": "ogc", + "ogg-Latn-NG": "ogg", + "ogo-Latn-NG": "ogo", + "ogu-Latn-NG": "ogu", + "oht-Xsux-TR": "oht", + "oia-Latn-ID": "oia", + "oie-Latn-SS": "oie", + "oin-Latn-PG": "oin", + "oj-Cans-CA": "oj", + "ojb-Cans-CA": "ojb-Cans", + "ojb-Latn-CA": "ojb", + "ojc-Latn-CA": "ojc", + "ojs-Cans-CA": "ojs", + "ojv-Latn-SB": "ojv", + "ojw-Cans-CA": "ojw-Cans", + "ojw-Latn-CA": "ojw", + "oka-Latn-CA": "oka", + "okb-Latn-NG": "okb", + "okc-Latn-CD": "okc", + "okd-Latn-NG": "okd", + "oke-Latn-NG": "oke", + "okg-Latn-AU": "okg", + "oki-Latn-KE": "oki", + "okk-Latn-PG": "okk", + "okm-Hang-KR": "okm", + "oko-Hani-KR": "oko", + "okr-Latn-ZZ": "okr", + "oks-Latn-NG": "oks", + "oku-Latn-CM": "oku", + "okv-Latn-ZZ": "okv", + "okx-Latn-NG": "okx", + "okz-Khmr-KH": "okz", + "ola-Deva-NP": "ola", + "ola-Tibt-CN": "ola-Tibt", + "old-Latn-TZ": "old", + "ole-Tibt-BT": "ole", + "olk-Latn-AU": "olk", + "olm-Latn-NG": "olm", + "olo-Latn-RU": "olo", + "olr-Latn-VU": "olr", + "olt-Latn-LT": "olt", + "olu-Latn-AO": "olu", + "om-Latn-ET": "om", + "oma-Latn-US": "oma", + "omb-Latn-VU": "omb", + "omc-Latn-PE": "omc", + "omg-Latn-PE": "omg", + "omi-Latn-CD": "omi", + "omk-Cyrl-RU": "omk", + "oml-Latn-CD": "oml", + "omo-Latn-PG": "omo", + "omp-Mtei-IN": "omp", + "omr-Modi-IN": "omr", + "omt-Latn-KE": "omt", + "omu-Latn-PE": "omu", + "omw-Latn-PG": "omw", + "ona-Latn-AR": "ona", + "one-Latn-CA": "one", + "ong-Latn-ZZ": "ong", + "oni-Latn-ID": "oni", + "onj-Latn-PG": "onj", + "onk-Latn-PG": "onk", + "onn-Latn-ZZ": "onn", + "ono-Latn-CA": "ono", + "onp-Deva-IN": "onp-Deva", + "onp-Latn-IN": "onp", + "onr-Latn-PG": "onr", + "ons-Latn-ZZ": "ons", + "ont-Latn-PG": "ont", + "onu-Latn-VU": "onu", + "onx-Latn-ID": "onx", + "ood-Latn-US": "ood", + "oon-Deva-IN": "oon", + "oor-Latn-ZA": "oor", + "opa-Latn-NG": "opa", + "opk-Latn-ID": "opk", + "opm-Latn-ZZ": "opm", + "opo-Latn-PG": "opo", + "opt-Latn-MX": "opt", + "opy-Latn-BR": "opy", + "or-Orya-IN": "or", + "ora-Latn-SB": "ora", + "orc-Latn-KE": "orc", + "ore-Latn-PE": "ore", + "org-Latn-NG": "org", + "orn-Latn-MY": "orn", + "oro-Latn-ZZ": "oro", + "orr-Latn-NG": "orr", + "ors-Latn-MY": "ors", + "ort-Telu-IN": "ort", + "oru-Arab-ZZ": "oru", + "orv-Cyrl-RU": "orv", + "orw-Latn-BR": "orw", + "orx-Latn-NG": "orx", + "orz-Latn-ID": "orz", + "os-Cyrl-GE": "os", + "osa-Osge-US": "osa", + "osc-Ital-IT": "osc", + "osc-Latn-IT": "osc-Latn", + "osi-Java-ID": "osi", + "oso-Latn-NG": "oso", + "osp-Latn-ES": "osp", + "ost-Latn-CM": "ost", + "osu-Latn-PG": "osu", + "osx-Latn-DE": "osx", + "ota-Arab-ZZ": "ota", + "otb-Tibt-CN": "otb", + "otd-Latn-ID": "otd", + "ote-Latn-MX": "ote", + "oti-Latn-BR": "oti", + "otk-Orkh-MN": "otk", + "otl-Latn-MX": "otl", + "otm-Latn-MX": "otm", + "otn-Latn-MX": "otn", + "otq-Latn-MX": "otq", + "otr-Latn-SD": "otr", + "ots-Latn-MX": "ots", + "ott-Latn-MX": "ott", + "otu-Latn-BR": "otu", + "otw-Latn-CA": "otw", + "otx-Latn-MX": "otx", + "oty-Gran-IN": "oty", + "otz-Latn-MX": "otz", + "oub-Latn-LR": "oub", + "oue-Latn-PG": "oue", + "oui-Ougr-143": "oui", + "oum-Latn-PG": "oum", + "ovd-Latn-SE": "ovd", + "owi-Latn-PG": "owi", + "owl-Latn-GB": "owl", + "oyd-Latn-ET": "oyd", + "oym-Latn-BR": "oym", + "oyy-Latn-PG": "oyy", + "ozm-Latn-ZZ": "ozm", + "pa-Arab-PK": "pa-PK", + "pa-Guru-IN": "pa", + "pab-Latn-BR": "pab", + "pac-Latn-VN": "pac", + "pad-Latn-BR": "pad", + "pae-Latn-CD": "pae", + "paf-Latn-BR": "paf", + "pag-Latn-PH": "pag", + "pah-Latn-BR": "pah", + "pai-Latn-NG": "pai", + "pak-Latn-BR": "pak", + "pal-Phli-IR": "pal", + "pal-Phlp-CN": "pal-Phlp", + "pam-Latn-PH": "pam", + "pao-Latn-US": "pao", + "pap-Latn-BQ": "pap-BQ", + "pap-Latn-CW": "pap", + "paq-Cyrl-TJ": "paq", + "par-Latn-US": "par", + "pas-Latn-ID": "pas", + "pau-Latn-PW": "pau", + "pav-Latn-BR": "pav", + "paw-Latn-US": "paw", + "pax-Latn-BR": "pax", + "pay-Latn-HN": "pay", + "paz-Latn-BR": "paz", + "pbb-Latn-CO": "pbb", + "pbc-Latn-GY": "pbc", + "pbe-Latn-MX": "pbe", + "pbf-Latn-MX": "pbf", + "pbg-Latn-VE": "pbg", + "pbh-Latn-VE": "pbh", + "pbi-Latn-ZZ": "pbi", + "pbl-Latn-NG": "pbl", + "pbm-Latn-MX": "pbm", + "pbn-Latn-NG": "pbn", + "pbo-Latn-GW": "pbo", + "pbp-Latn-GN": "pbp", + "pbr-Latn-TZ": "pbr", + "pbs-Latn-MX": "pbs", + "pbt-Arab-AF": "pbt", + "pbv-Latn-IN": "pbv", + "pby-Latn-PG": "pby", + "pca-Latn-MX": "pca", + "pcb-Khmr-KH": "pcb", + "pcc-Hani-CN": "pcc-Hani", + "pcc-Latn-CN": "pcc", + "pcd-Latn-FR": "pcd", + "pce-Mymr-MM": "pce", + "pce-Thai-TH": "pce-Thai", + "pcf-Mlym-IN": "pcf", + "pcg-Knda-IN": "pcg-Knda", + "pcg-Mlym-IN": "pcg", + "pcg-Taml-IN": "pcg-Taml", + "pch-Deva-IN": "pch", + "pci-Deva-IN": "pci", + "pci-Orya-IN": "pci-Orya", + "pcj-Telu-IN": "pcj", + "pck-Latn-IN": "pck", + "pcm-Latn-NG": "pcm", + "pcn-Latn-NG": "pcn", + "pcp-Latn-BO": "pcp", + "pcw-Latn-NG": "pcw", + "pda-Latn-PG": "pda", + "pdc-Latn-US": "pdc", + "pdn-Latn-ID": "pdn", + "pdo-Latn-ID": "pdo", + "pdt-Latn-CA": "pdt", + "pdu-Latn-MM": "pdu", + "pdu-Mymr-MM": "pdu-Mymr", + "pea-Latn-ID": "pea", + "peb-Latn-US": "peb", + "ped-Latn-ZZ": "ped", + "pee-Latn-ID": "pee", + "peg-Orya-IN": "peg", + "pei-Latn-MX": "pei", + "pek-Latn-PG": "pek", + "pel-Latn-ID": "pel", + "pem-Latn-CD": "pem", + "peo-Xpeo-IR": "peo", + "pep-Latn-PG": "pep", + "peq-Latn-US": "peq", + "pev-Latn-VE": "pev", + "pex-Latn-ZZ": "pex", + "pey-Latn-ID": "pey", + "pez-Latn-MY": "pez", + "pfa-Latn-FM": "pfa", + "pfe-Latn-CM": "pfe", + "pfl-Latn-DE": "pfl", + "pga-Latn-SS": "pga", + "pgd-Khar-PK": "pgd", + "pgg-Deva-IN": "pgg", + "pgi-Latn-PG": "pgi", + "pgk-Latn-VU": "pgk", + "pgl-Ogam-IE": "pgl", + "pgn-Ital-IT": "pgn", + "pgs-Latn-NG": "pgs", + "pgu-Latn-ID": "pgu", + "phd-Deva-IN": "phd", + "phg-Latn-VN": "phg", + "phh-Latn-VN": "phh", + "phk-Mymr-IN": "phk", + "phl-Arab-ZZ": "phl", + "phm-Latn-MZ": "phm", + "phn-Phnx-LB": "phn", + "pho-Laoo-LA": "pho", + "phr-Arab-PK": "phr", + "pht-Thai-TH": "pht", + "phv-Arab-AF": "phv", + "phw-Deva-NP": "phw", + "pi-Brah-IN": "pi-Brah", + "pi-Deva-IN": "pi-Deva", + "pi-Khar-IN": "pi-Khar", + "pi-Khmr-IN": "pi-Khmr", + "pi-Mymr-IN": "pi-Mymr", + "pi-Sinh-IN": "pi", + "pi-Thai-IN": "pi-Thai", + "pia-Latn-MX": "pia", + "pib-Latn-PE": "pib", + "pic-Latn-GA": "pic", + "pid-Latn-VE": "pid", + "pif-Latn-FM": "pif", + "pig-Latn-PE": "pig", + "pih-Latn-NF": "pih", + "pij-Latn-CO": "pij", + "pil-Latn-ZZ": "pil", + "pim-Latn-US": "pim", + "pin-Latn-PG": "pin", + "pio-Latn-CO": "pio", + "pip-Latn-ZZ": "pip", + "pir-Latn-BR": "pir", + "pis-Latn-SB": "pis", + "pit-Latn-AU": "pit", + "piu-Latn-AU": "piu", + "piv-Latn-SB": "piv", + "piw-Latn-TZ": "piw", + "pix-Latn-PG": "pix", + "piy-Latn-NG": "piy", + "piz-Latn-NC": "piz", + "pjt-Latn-AU": "pjt", + "pka-Brah-IN": "pka", + "pkb-Latn-KE": "pkb", + "pkg-Latn-PG": "pkg", + "pkh-Deva-BD": "pkh-Deva", + "pkh-Latn-BD": "pkh", + "pkn-Latn-AU": "pkn", + "pko-Latn-KE": "pko", + "pkp-Latn-CK": "pkp", + "pkr-Mlym-IN": "pkr", + "pku-Latn-ID": "pku", + "pl-Latn-PL": "pl", + "pl-Latn-UA": "pl-UA", + "pla-Latn-ZZ": "pla", + "plb-Latn-VU": "plb", + "plc-Latn-PH": "plc", + "pld-Latn-GB": "pld", + "ple-Latn-ID": "ple", + "plg-Latn-AR": "plg", + "plh-Latn-ID": "plh", + "plj-Latn-NG": "plj", + "plk-Arab-PK": "plk", + "pll-Mymr-MM": "pll", + "pln-Latn-CO": "pln", + "plo-Latn-MX": "plo", + "plr-Latn-CI": "plr", + "pls-Latn-MX": "pls", + "plu-Latn-BR": "plu", + "plv-Latn-PH": "plv", + "plw-Latn-PH": "plw", + "plz-Latn-MY": "plz", + "pma-Latn-VU": "pma", + "pmb-Latn-CD": "pmb", + "pmd-Latn-AU": "pmd", + "pme-Latn-NC": "pme", + "pmf-Latn-ID": "pmf", + "pmh-Brah-IN": "pmh", + "pmi-Latn-CN": "pmi", + "pmj-Latn-CN": "pmj", + "pml-Latn-TN": "pml", + "pmm-Latn-CM": "pmm", + "pmn-Latn-CM": "pmn", + "pmo-Latn-ID": "pmo", + "pmq-Latn-MX": "pmq", + "pmr-Latn-PG": "pmr", + "pms-Latn-IT": "pms", + "pmt-Latn-PF": "pmt", + "pmw-Latn-US": "pmw", + "pmx-Latn-IN": "pmx", + "pmy-Latn-ID": "pmy", + "pmz-Latn-MX": "pmz", + "pna-Latn-MY": "pna", + "pnc-Latn-ID": "pnc", + "pnd-Latn-AO": "pnd", + "pne-Latn-MY": "pne", + "png-Latn-ZZ": "png", + "pnh-Latn-CK": "pnh", + "pni-Latn-ID": "pni", + "pnj-Latn-AU": "pnj", + "pnk-Latn-BO": "pnk", + "pnl-Latn-BF": "pnl", + "pnm-Latn-MY": "pnm", + "pnn-Latn-ZZ": "pnn", + "pno-Latn-PE": "pno", + "pnp-Latn-ID": "pnp", + "pnq-Latn-BF": "pnq", + "pnr-Latn-PG": "pnr", + "pns-Latn-ID": "pns", + "pnt-Grek-GR": "pnt", + "pnv-Latn-AU": "pnv", + "pnw-Latn-AU": "pnw", + "pny-Latn-CM": "pny", + "pnz-Latn-CF": "pnz", + "poc-Latn-GT": "poc", + "poe-Latn-MX": "poe", + "pof-Latn-CD": "pof", + "pog-Latn-BR": "pog", + "poh-Latn-GT": "poh", + "poi-Latn-MX": "poi", + "pok-Latn-BR": "pok", + "pom-Latn-US": "pom", + "pon-Latn-FM": "pon", + "poo-Latn-US": "poo", + "pop-Latn-NC": "pop", + "poq-Latn-MX": "poq", + "pos-Latn-MX": "pos", + "pot-Latn-US": "pot", + "pov-Latn-GW": "pov", + "pow-Latn-MX": "pow", + "poy-Latn-TZ": "poy", + "ppe-Latn-PG": "ppe", + "ppi-Latn-MX": "ppi", + "ppk-Latn-ID": "ppk", + "ppl-Latn-SV": "ppl", + "ppm-Latn-ID": "ppm", + "ppn-Latn-PG": "ppn", + "ppo-Latn-ZZ": "ppo", + "ppp-Latn-CD": "ppp", + "ppq-Latn-PG": "ppq", + "pps-Latn-MX": "pps", + "ppt-Latn-PG": "ppt", + "pqa-Latn-NG": "pqa", + "pqm-Latn-CA": "pqm", + "pra-Khar-PK": "pra", + "prc-Arab-AF": "prc", + "prd-Arab-IR": "prd", + "pre-Latn-ST": "pre", + "prf-Latn-PH": "prf", + "prg-Latn-001": "prg", + "prh-Latn-PH": "prh", + "pri-Latn-NC": "pri", + "prk-Latn-MM": "prk", + "prm-Latn-PG": "prm", + "pro-Latn-FR": "pro", + "prp-Gujr-IN": "prp", + "prq-Latn-PE": "prq", + "prr-Latn-BR": "prr", + "prt-Thai-TH": "prt", + "pru-Latn-ID": "pru", + "prw-Latn-PG": "prw", + "prx-Arab-IN": "prx", + "prx-Tibt-IN": "prx-Tibt", + "ps-Arab-AF": "ps", + "psa-Latn-ID": "psa", + "pse-Latn-ID": "pse", + "psh-Arab-AF": "psh", + "psi-Arab-AF": "psi", + "psm-Latn-BO": "psm", + "psn-Latn-ID": "psn", + "psq-Latn-PG": "psq", + "pss-Latn-ZZ": "pss", + "pst-Arab-PK": "pst", + "psw-Latn-VU": "psw", + "pt-Latn-AO": "pt-AO", + "pt-Latn-BR": "pt", + "pt-Latn-CV": "pt-CV", + "pt-Latn-GW": "pt-GW", + "pt-Latn-MO": "pt-MO", + "pt-Latn-MZ": "pt-MZ", + "pt-Latn-PT": "pt-PT", + "pt-Latn-ST": "pt-ST", + "pt-Latn-TL": "pt-TL", + "pta-Latn-PY": "pta", + "pth-Latn-BR": "pth", + "pti-Latn-AU": "pti", + "ptn-Latn-ID": "ptn", + "pto-Latn-BR": "pto", + "ptp-Latn-ZZ": "ptp", + "ptr-Latn-VU": "ptr", + "ptt-Latn-ID": "ptt", + "ptu-Latn-ID": "ptu", + "ptv-Latn-VU": "ptv", + "pua-Latn-MX": "pua", + "pub-Latn-IN": "pub", + "puc-Latn-ID": "puc", + "pud-Latn-ID": "pud", + "pue-Latn-AR": "pue", + "puf-Latn-ID": "puf", + "pug-Latn-BF": "pug", + "pui-Latn-CO": "pui", + "puj-Latn-ID": "puj", + "pum-Deva-NP": "pum", + "puo-Latn-VN": "puo", + "pup-Latn-PG": "pup", + "puq-Latn-PE": "puq", + "pur-Latn-BR": "pur", + "put-Latn-ID": "put", + "puu-Latn-GA": "puu", + "puw-Latn-FM": "puw", + "pux-Latn-PG": "pux", + "puy-Latn-US": "puy", + "pwa-Latn-ZZ": "pwa", + "pwb-Latn-NG": "pwb", + "pwg-Latn-PG": "pwg", + "pwm-Latn-PH": "pwm", + "pwn-Latn-TW": "pwn", + "pwo-Mymr-MM": "pwo", + "pwr-Deva-IN": "pwr", + "pww-Thai-TH": "pww", + "pxm-Latn-MX": "pxm", + "pye-Latn-CI": "pye", + "pym-Latn-NG": "pym", + "pyn-Latn-BR": "pyn", + "pyu-Hani-TW": "pyu-Hani", + "pyu-Latn-TW": "pyu", + "pyx-Mymr-MM": "pyx", + "pyy-Latn-MM": "pyy", + "pzh-Latn-TW": "pzh", + "pzn-Latn-MM": "pzn", + "qu-Latn-PE": "qu", + "qua-Latn-US": "qua", + "qub-Latn-PE": "qub", + "quc-Latn-GT": "quc", + "qud-Latn-EC": "qud", + "quf-Latn-PE": "quf", + "qug-Latn-EC": "qug", + "qui-Latn-US": "qui", + "quk-Latn-PE": "quk", + "qul-Latn-BO": "qul", + "qum-Latn-GT": "qum", + "qun-Latn-US": "qun", + "qup-Latn-PE": "qup", + "quq-Latn-ES": "quq", + "qur-Latn-PE": "qur", + "qus-Latn-AR": "qus", + "quv-Latn-GT": "quv", + "quw-Latn-EC": "quw", + "qux-Latn-PE": "qux", + "quy-Latn-PE": "quy", + "qva-Latn-PE": "qva", + "qvc-Latn-PE": "qvc", + "qve-Latn-PE": "qve", + "qvh-Latn-PE": "qvh", + "qvi-Latn-EC": "qvi", + "qvj-Latn-EC": "qvj", + "qvl-Latn-PE": "qvl", + "qvm-Latn-PE": "qvm", + "qvn-Latn-PE": "qvn", + "qvo-Latn-PE": "qvo", + "qvp-Latn-PE": "qvp", + "qvs-Latn-PE": "qvs", + "qvw-Latn-PE": "qvw", + "qvz-Latn-EC": "qvz", + "qwa-Latn-PE": "qwa", + "qwc-Latn-PE": "qwc", + "qwh-Latn-PE": "qwh", + "qwm-Cyrl-RU": "qwm-Cyrl", + "qwm-Latn-RU": "qwm", + "qwm-Runr-RU": "qwm-Runr", + "qws-Latn-PE": "qws", + "qwt-Latn-US": "qwt", + "qxa-Latn-PE": "qxa", + "qxc-Latn-PE": "qxc", + "qxh-Latn-PE": "qxh", + "qxl-Latn-EC": "qxl", + "qxn-Latn-PE": "qxn", + "qxo-Latn-PE": "qxo", + "qxp-Latn-PE": "qxp", + "qxq-Arab-IR": "qxq", + "qxr-Latn-EC": "qxr", + "qxt-Latn-PE": "qxt", + "qxu-Latn-PE": "qxu", + "qxw-Latn-PE": "qxw", + "qya-Latn-001": "qya", + "qyp-Latn-US": "qyp", + "raa-Deva-NP": "raa", + "rab-Deva-NP": "rab", + "rac-Latn-ID": "rac", + "rad-Latn-VN": "rad", + "raf-Deva-NP": "raf", + "rag-Latn-KE": "rag", + "rah-Beng-IN": "rah", + "rah-Latn-IN": "rah-Latn", + "rai-Latn-ZZ": "rai", + "raj-Deva-IN": "raj", + "rak-Latn-PG": "rak", + "ram-Latn-BR": "ram", + "ran-Latn-ID": "ran", + "rao-Latn-ZZ": "rao", + "rap-Latn-CL": "rap", + "rar-Latn-CK": "rar", + "rav-Deva-NP": "rav", + "raw-Latn-MM": "raw", + "rax-Latn-NG": "rax", + "ray-Latn-PF": "ray", + "raz-Latn-ID": "raz", + "rbb-Mymr-MM": "rbb", + "rbk-Latn-PH": "rbk", + "rbl-Latn-PH": "rbl", + "rbp-Latn-AU": "rbp", + "rcf-Latn-RE": "rcf", + "rdb-Arab-IR": "rdb", + "rea-Latn-PG": "rea", + "reb-Latn-ID": "reb", + "ree-Latn-MY": "ree", + "reg-Latn-TZ": "reg", + "rei-Orya-IN": "rei", + "rei-Telu-IN": "rei-Telu", + "rej-Latn-ID": "rej", + "rej-Rjng-ID": "rej-Rjng", + "rel-Latn-ZZ": "rel", + "rem-Latn-PE": "rem", + "ren-Latn-VN": "ren", + "res-Latn-ZZ": "res", + "ret-Latn-ID": "ret", + "rey-Latn-BO": "rey", + "rga-Latn-VU": "rga", + "rgn-Latn-IT": "rgn", + "rgr-Latn-PE": "rgr", + "rgs-Latn-VN": "rgs", + "rgu-Latn-ID": "rgu", + "rhg-Arab-MM": "rhg-Arab", + "rhg-Rohg-MM": "rhg", + "rhp-Latn-PG": "rhp", + "ria-Latn-IN": "ria", + "rif-Latn-MA": "rif", + "ril-Latn-MM": "ril", + "rim-Latn-TZ": "rim", + "rin-Latn-NG": "rin", + "rir-Latn-ID": "rir", + "rit-Latn-AU": "rit", + "riu-Latn-ID": "riu", + "rjg-Latn-ID": "rjg", + "rji-Deva-NP": "rji", + "rjs-Deva-NP": "rjs", + "rka-Khmr-KH": "rka", + "rkb-Latn-BR": "rkb", + "rkh-Latn-CK": "rkh", + "rki-Mymr-MM": "rki", + "rkm-Latn-BF": "rkm", + "rkt-Beng-BD": "rkt", + "rkw-Latn-AU": "rkw", + "rm-Latn-CH": "rm", + "rma-Latn-NI": "rma", + "rmb-Latn-AU": "rmb", + "rmc-Latn-SK": "rmc", + "rmd-Latn-DK": "rmd", + "rme-Latn-GB": "rme", + "rmf-Latn-FI": "rmf", + "rmg-Latn-NO": "rmg", + "rmh-Latn-ID": "rmh", + "rmi-Armn-AM": "rmi", + "rmk-Latn-PG": "rmk", + "rml-Cyrl-BY": "rml-Cyrl", + "rml-Latn-PL": "rml", + "rmm-Latn-ID": "rmm", + "rmn-Cyrl-BG": "rmn-Cyrl", + "rmn-Grek-GR": "rmn-Grek", + "rmn-Latn-RS": "rmn", + "rmo-Latn-CH": "rmo", + "rmp-Latn-PG": "rmp", + "rmq-Latn-ES": "rmq", + "rmt-Arab-IR": "rmt", + "rmu-Latn-SE": "rmu", + "rmw-Latn-GB": "rmw", + "rmx-Latn-VN": "rmx", + "rmz-Mymr-IN": "rmz", + "rn-Latn-BI": "rn", + "rna-Latn-ZZ": "rna", + "rnd-Latn-CD": "rnd", + "rng-Latn-MZ": "rng", + "rnl-Latn-IN": "rnl", + "rnn-Latn-ID": "rnn", + "rnr-Latn-AU": "rnr", + "rnw-Latn-TZ": "rnw", + "ro-Latn-MD": "ro-MD", + "ro-Latn-RO": "ro", + "rob-Latn-ID": "rob", + "roc-Latn-VN": "roc", + "rod-Latn-NG": "rod", + "roe-Latn-PG": "roe", + "rof-Latn-TZ": "rof", + "rog-Latn-VN": "rog", + "rol-Latn-PH": "rol", + "rom-Cyrl-RO": "rom-Cyrl", + "rom-Latn-RO": "rom", + "roo-Latn-ZZ": "roo", + "rop-Latn-AU": "rop", + "ror-Latn-ID": "ror", + "rou-Latn-TD": "rou", + "row-Latn-ID": "row", + "rpn-Latn-VU": "rpn", + "rpt-Latn-PG": "rpt", + "rri-Latn-SB": "rri", + "rro-Latn-ZZ": "rro", + "rrt-Latn-AU": "rrt", + "rsk-Cyrl-RS": "rsk", + "rtc-Latn-MM": "rtc", + "rth-Latn-ID": "rth", + "rtm-Latn-FJ": "rtm", + "rtw-Deva-IN": "rtw", + "ru-Cyrl-KZ": "ru-KZ", + "ru-Cyrl-RU": "ru", + "rub-Latn-UG": "rub", + "ruc-Latn-UG": "ruc", + "rue-Cyrl-UA": "rue", + "ruf-Latn-TZ": "ruf", + "rug-Latn-SB": "rug", + "rui-Latn-TZ": "rui", + "ruk-Latn-NG": "ruk", + "ruo-Latn-HR": "ruo", + "rup-Grek-GR": "rup-Grek", + "rup-Latn-RO": "rup", + "ruq-Latn-GR": "ruq", + "rut-Cyrl-RU": "rut", + "rut-Latn-AZ": "rut-Latn", + "ruu-Latn-MY": "ruu", + "ruy-Latn-NG": "ruy", + "ruz-Latn-NG": "ruz", + "rw-Latn-RW": "rw", + "rwa-Latn-PG": "rwa", + "rwk-Latn-TZ": "rwk", + "rwl-Latn-TZ": "rwl", + "rwm-Latn-UG": "rwm", + "rwo-Latn-ZZ": "rwo", + "rwr-Deva-IN": "rwr", + "rxd-Latn-AU": "rxd", + "rxw-Latn-AU": "rxw", + "ryu-Kana-JP": "ryu", + "sa-Bhks-IN": "sa-Bhks", + "sa-Deva-IN": "sa", + "sa-Gran-IN": "sa-Gran", + "sa-Nand-IN": "sa-Nand", + "sa-Shrd-IN": "sa-Shrd", + "sa-Sidd-IN": "sa-Sidd", + "saa-Latn-TD": "saa", + "sab-Latn-PA": "sab", + "sac-Latn-US": "sac", + "sad-Latn-TZ": "sad", + "sae-Latn-BR": "sae", + "saf-Latn-GH": "saf", + "sah-Cyrl-RU": "sah", + "saj-Latn-ID": "saj", + "sak-Latn-GA": "sak", + "sam-Hebr-PS": "sam-Hebr", + "sam-Samr-PS": "sam", + "sam-Syrc-PS": "sam-Syrc", + "sao-Latn-ID": "sao", + "saq-Latn-KE": "saq", + "sar-Latn-BO": "sar", + "sas-Latn-ID": "sas", + "sat-Olck-IN": "sat", + "sau-Latn-ID": "sau", + "sav-Latn-SN": "sav", + "saw-Latn-ID": "saw", + "sax-Latn-VU": "sax", + "say-Latn-NG": "say", + "saz-Saur-IN": "saz", + "sba-Latn-ZZ": "sba", + "sbb-Latn-SB": "sbb", + "sbc-Latn-PG": "sbc", + "sbd-Latn-BF": "sbd", + "sbe-Latn-ZZ": "sbe", + "sbg-Latn-ID": "sbg", + "sbh-Latn-PG": "sbh", + "sbi-Latn-PG": "sbi", + "sbj-Latn-TD": "sbj", + "sbk-Latn-TZ": "sbk", + "sbl-Latn-PH": "sbl", + "sbm-Latn-TZ": "sbm", + "sbn-Arab-PK": "sbn", + "sbo-Latn-MY": "sbo", + "sbp-Latn-TZ": "sbp", + "sbq-Latn-PG": "sbq", + "sbr-Latn-ID": "sbr", + "sbs-Latn-NA": "sbs", + "sbt-Latn-ID": "sbt", + "sbu-Deva-IN": "sbu-Deva", + "sbu-Tibt-IN": "sbu", + "sbv-Latn-IT": "sbv", + "sbw-Latn-GA": "sbw", + "sbx-Latn-ID": "sbx", + "sby-Latn-ZM": "sby", + "sbz-Latn-CF": "sbz", + "sc-Latn-IT": "sc", + "scb-Latn-VN": "scb", + "sce-Arab-CN": "sce-Arab", + "sce-Latn-CN": "sce", + "scf-Latn-PA": "scf", + "scg-Latn-ID": "scg", + "sch-Latn-IN": "sch", + "sci-Latn-LK": "sci", + "sck-Deva-IN": "sck", + "scl-Arab-ZZ": "scl", + "scn-Latn-IT": "scn", + "sco-Latn-GB": "sco", + "scp-Deva-NP": "scp", + "scs-Cans-CA": "scs-Cans", + "scs-Latn-CA": "scs", + "sct-Laoo-LA": "sct", + "scu-Takr-IN": "scu", + "scv-Latn-NG": "scv", + "scw-Latn-NG": "scw", + "scx-Grek-IT": "scx", + "sd-Arab-PK": "sd", + "sd-Deva-IN": "sd-IN", + "sd-Khoj-IN": "sd-Khoj", + "sd-Sind-IN": "sd-Sind", + "sda-Latn-ID": "sda", + "sdb-Arab-IQ": "sdb", + "sdc-Latn-IT": "sdc", + "sde-Latn-NG": "sde", + "sdf-Arab-IQ": "sdf", + "sdg-Arab-AF": "sdg", + "sdh-Arab-IR": "sdh", + "sdj-Latn-CG": "sdj", + "sdk-Latn-PG": "sdk", + "sdn-Latn-IT": "sdn", + "sdo-Latn-MY": "sdo", + "sdq-Latn-ID": "sdq", + "sds-Arab-TN": "sds", + "sdu-Latn-ID": "sdu", + "sdx-Latn-MY": "sdx", + "se-Latn-NO": "se", + "sea-Latn-MY": "sea", + "seb-Latn-CI": "seb", + "sec-Latn-CA": "sec", + "sed-Latn-VN": "sed", + "see-Latn-US": "see", + "sef-Latn-CI": "sef", + "seg-Latn-TZ": "seg", + "seh-Latn-MZ": "seh", + "sei-Latn-MX": "sei", + "sej-Latn-PG": "sej", + "sek-Cans-CA": "sek-Cans", + "sek-Latn-CA": "sek", + "sel-Cyrl-RU": "sel", + "sen-Latn-BF": "sen", + "seo-Latn-PG": "seo", + "sep-Latn-BF": "sep", + "seq-Latn-BF": "seq", + "ser-Latn-US": "ser", + "ses-Latn-ML": "ses", + "set-Latn-ID": "set", + "seu-Latn-ID": "seu", + "sev-Latn-CI": "sev", + "sew-Latn-PG": "sew", + "sey-Latn-EC": "sey", + "sez-Latn-MM": "sez", + "sfe-Latn-PH": "sfe", + "sfm-Plrd-CN": "sfm", + "sfw-Latn-GH": "sfw", + "sg-Latn-CF": "sg", + "sga-Ogam-IE": "sga", + "sgb-Latn-PH": "sgb", + "sgc-Latn-KE": "sgc", + "sgd-Latn-PH": "sgd", + "sge-Latn-ID": "sge", + "sgh-Arab-AF": "sgh-Arab", + "sgh-Cyrl-TJ": "sgh", + "sgh-Latn-TJ": "sgh-Latn", + "sgi-Latn-CM": "sgi", + "sgj-Deva-IN": "sgj", + "sgm-Latn-KE": "sgm", + "sgp-Latn-IN": "sgp", + "sgr-Arab-IR": "sgr", + "sgs-Latn-LT": "sgs", + "sgt-Tibt-BT": "sgt", + "sgu-Latn-ID": "sgu", + "sgw-Ethi-ZZ": "sgw", + "sgy-Arab-AF": "sgy", + "sgz-Latn-ZZ": "sgz", + "sha-Latn-NG": "sha", + "shb-Latn-BR": "shb", + "shc-Latn-CD": "shc", + "shd-Arab-PK": "shd", + "she-Latn-ET": "she", + "shg-Latn-BW": "shg", + "shh-Latn-US": "shh", + "shi-Tfng-MA": "shi", + "shj-Latn-SD": "shj", + "shk-Latn-ZZ": "shk", + "shm-Arab-IR": "shm", + "shn-Mymr-MM": "shn", + "sho-Latn-NG": "sho", + "shp-Latn-PE": "shp", + "shq-Latn-ZM": "shq", + "shr-Latn-CD": "shr", + "shs-Latn-CA": "shs", + "sht-Latn-US": "sht", + "shu-Arab-ZZ": "shu", + "shv-Arab-OM": "shv", + "shw-Latn-SD": "shw", + "shy-Arab-DZ": "shy-Arab", + "shy-Latn-DZ": "shy", + "shy-Tfng-DZ": "shy-Tfng", + "shz-Latn-ML": "shz", + "si-Sinh-LK": "si", + "sia-Cyrl-RU": "sia", + "sib-Latn-MY": "sib", + "sid-Latn-ET": "sid", + "sie-Latn-ZM": "sie", + "sif-Latn-BF": "sif", + "sig-Latn-ZZ": "sig", + "sih-Latn-NC": "sih", + "sii-Latn-IN": "sii", + "sij-Latn-PG": "sij", + "sik-Latn-BR": "sik", + "sil-Latn-ZZ": "sil", + "sim-Latn-ZZ": "sim", + "sip-Tibt-IN": "sip", + "siq-Latn-PG": "siq", + "sir-Latn-NG": "sir", + "sis-Latn-US": "sis", + "siu-Latn-PG": "siu", + "siv-Latn-PG": "siv", + "siw-Latn-PG": "siw", + "six-Latn-PG": "six", + "siy-Arab-IR": "siy", + "siz-Arab-EG": "siz", + "sja-Latn-CO": "sja", + "sjb-Latn-ID": "sjb", + "sjd-Cyrl-RU": "sjd", + "sje-Latn-SE": "sje", + "sjg-Latn-TD": "sjg", + "sjl-Latn-IN": "sjl", + "sjm-Latn-PH": "sjm", + "sjp-Beng-IN": "sjp-Beng", + "sjp-Deva-IN": "sjp", + "sjr-Latn-ZZ": "sjr", + "sjt-Cyrl-RU": "sjt", + "sju-Latn-SE": "sju", + "sjw-Latn-US": "sjw", + "sk-Latn-SK": "sk", + "ska-Latn-US": "ska", + "skb-Thai-TH": "skb", + "skc-Latn-ZZ": "skc", + "skd-Latn-US": "skd", + "ske-Latn-VU": "ske", + "skf-Latn-BR": "skf", + "skg-Latn-MG": "skg", + "skh-Latn-ID": "skh", + "ski-Latn-ID": "ski", + "skj-Deva-NP": "skj", + "skm-Latn-PG": "skm", + "skn-Latn-PH": "skn", + "sko-Latn-ID": "sko", + "skp-Latn-MY": "skp", + "skq-Latn-BF": "skq", + "skr-Arab-PK": "skr", + "skr-Mult-PK": "skr-Mult", + "sks-Latn-ZZ": "sks", + "skt-Latn-CD": "skt", + "sku-Latn-VU": "sku", + "skv-Latn-ID": "skv", + "skw-Latn-GY": "skw", + "skx-Latn-ID": "skx", + "sky-Latn-SB": "sky", + "skz-Latn-ID": "skz", + "sl-Latn-SI": "sl", + "slc-Latn-CO": "slc", + "sld-Latn-ZZ": "sld", + "slg-Latn-ID": "slg", + "slh-Latn-US": "slh", + "sli-Latn-PL": "sli", + "slj-Latn-BR": "slj", + "sll-Latn-ZZ": "sll", + "slm-Latn-PH": "slm", + "sln-Latn-US": "sln", + "slp-Latn-ID": "slp", + "slq-Arab-IR": "slq", + "slr-Latn-CN": "slr", + "slu-Latn-ID": "slu", + "slw-Latn-PG": "slw", + "slx-Latn-CD": "slx", + "sly-Latn-ID": "sly", + "slz-Latn-ID": "slz", + "sm-Latn-AS": "sm-AS", + "sm-Latn-WS": "sm", + "sma-Latn-SE": "sma", + "smb-Latn-PG": "smb", + "smc-Latn-PG": "smc", + "smf-Latn-PG": "smf", + "smg-Latn-PG": "smg", + "smh-Yiii-CN": "smh", + "smj-Latn-SE": "smj", + "smk-Latn-PH": "smk", + "sml-Latn-PH": "sml", + "smn-Latn-FI": "smn", + "smp-Samr-IL": "smp", + "smq-Latn-ZZ": "smq", + "smr-Latn-ID": "smr", + "sms-Latn-FI": "sms", + "smt-Latn-IN": "smt", + "smu-Khmr-KH": "smu", + "smw-Latn-ID": "smw", + "smx-Latn-CD": "smx", + "smy-Arab-IR": "smy", + "smz-Latn-PG": "smz", + "sn-Latn-ZW": "sn", + "snc-Latn-ZZ": "snc", + "sne-Latn-MY": "sne", + "snf-Latn-SN": "snf", + "sng-Brai-CD": "sng-Brai", + "sng-Latn-CD": "sng", + "sni-Latn-PE": "sni", + "snj-Latn-CF": "snj", + "snk-Latn-ML": "snk", + "snl-Latn-PH": "snl", + "snm-Latn-UG": "snm", + "snn-Latn-CO": "snn", + "sno-Latn-US": "sno", + "snp-Latn-ZZ": "snp", + "snq-Latn-GA": "snq", + "snr-Latn-PG": "snr", + "sns-Latn-VU": "sns", + "snu-Latn-ID": "snu", + "snv-Latn-MY": "snv", + "snw-Latn-GH": "snw", + "snx-Latn-ZZ": "snx", + "sny-Latn-ZZ": "sny", + "snz-Latn-PG": "snz", + "so-Latn-SO": "so", + "so-Osma-SO": "so-Osma", + "soa-Tavt-TH": "soa", + "soa-Thai-TH": "soa-Thai", + "sob-Latn-ID": "sob", + "soc-Latn-CD": "soc", + "sod-Latn-CD": "sod", + "soe-Latn-CD": "soe", + "sog-Sogd-UZ": "sog", + "sog-Sogo-UZ": "sog-Sogo", + "soi-Deva-NP": "soi", + "sok-Latn-ZZ": "sok", + "sol-Latn-PG": "sol", + "soo-Latn-CD": "soo", + "sop-Latn-CD": "sop", + "soq-Latn-ZZ": "soq", + "sor-Latn-TD": "sor", + "sos-Latn-BF": "sos", + "sou-Thai-TH": "sou", + "sov-Latn-PW": "sov", + "sow-Latn-PG": "sow", + "sox-Latn-CM": "sox", + "soy-Latn-ZZ": "soy", + "soz-Latn-TZ": "soz", + "spb-Latn-ID": "spb", + "spc-Latn-VE": "spc", + "spd-Latn-ZZ": "spd", + "spe-Latn-PG": "spe", + "spg-Latn-MY": "spg", + "spi-Latn-ID": "spi", + "spk-Latn-PG": "spk", + "spl-Latn-ZZ": "spl", + "spm-Latn-PG": "spm", + "spn-Latn-PY": "spn", + "spo-Latn-US": "spo", + "spp-Latn-ML": "spp", + "spq-Latn-PE": "spq", + "spr-Latn-ID": "spr", + "sps-Latn-ZZ": "sps", + "spt-Tibt-IN": "spt", + "spv-Orya-IN": "spv", + "sq-Elba-AL": "sq-Elba", + "sq-Latn-AL": "sq", + "sq-Latn-MK": "sq-MK", + "sq-Latn-XK": "sq-XK", + "sq-Vith-AL": "sq-Vith", + "sqa-Latn-NG": "sqa", + "sqh-Latn-NG": "sqh", + "sqm-Latn-CF": "sqm", + "sqo-Arab-IR": "sqo", + "sqq-Laoo-LA": "sqq", + "sqt-Arab-YE": "sqt", + "sqt-Latn-YE": "sqt-Latn", + "squ-Latn-CA": "squ", + "sr-Cyrl-BA": "sr-BA", + "sr-Cyrl-RS": "sr", + "sr-Cyrl-XK": "sr-XK", + "sr-Latn-ME": "sr-ME", + "sr-Latn-RO": "sr-RO", + "sr-Latn-RU": "sr-RU", + "sr-Latn-TR": "sr-TR", + "sra-Latn-PG": "sra", + "srb-Sora-IN": "srb", + "sre-Latn-ID": "sre", + "srf-Latn-PG": "srf", + "srg-Latn-PH": "srg", + "srh-Arab-CN": "srh", + "sri-Latn-CO": "sri", + "srk-Latn-MY": "srk", + "srl-Latn-ID": "srl", + "srm-Latn-SR": "srm", + "srn-Latn-SR": "srn", + "sro-Latn-IT": "sro", + "srq-Latn-BO": "srq", + "srr-Latn-SN": "srr", + "srs-Latn-CA": "srs", + "srt-Latn-ID": "srt", + "sru-Latn-BR": "sru", + "srv-Latn-PH": "srv", + "srw-Latn-ID": "srw", + "srx-Deva-IN": "srx", + "sry-Latn-PG": "sry", + "srz-Arab-IR": "srz", + "ss-Latn-ZA": "ss", + "ssb-Latn-PH": "ssb", + "ssc-Latn-TZ": "ssc", + "ssd-Latn-ZZ": "ssd", + "sse-Arab-PH": "sse-Arab", + "sse-Latn-PH": "sse", + "ssf-Latn-TW": "ssf", + "ssg-Latn-ZZ": "ssg", + "ssh-Arab-AE": "ssh", + "ssj-Latn-PG": "ssj", + "ssl-Latn-GH": "ssl", + "ssm-Latn-MY": "ssm", + "ssn-Latn-KE": "ssn", + "sso-Latn-PG": "sso", + "ssq-Latn-ID": "ssq", + "sss-Laoo-LA": "sss", + "sss-Thai-TH": "sss-Thai", + "sst-Latn-PG": "sst", + "ssu-Latn-PG": "ssu", + "ssv-Latn-VU": "ssv", + "ssx-Latn-PG": "ssx", + "ssy-Latn-ER": "ssy", + "ssz-Latn-PG": "ssz", + "st-Latn-LS": "st-LS", + "st-Latn-ZA": "st", + "sta-Latn-ZM": "sta", + "stb-Latn-PH": "stb", + "ste-Latn-ID": "ste", + "stf-Latn-PG": "stf", + "stg-Latn-VN": "stg", + "sth-Latn-IE": "sth", + "sti-Latn-KH": "sti-KH", + "sti-Latn-VN": "sti", + "stj-Latn-BF": "stj", + "stk-Latn-ZZ": "stk", + "stl-Latn-NL": "stl", + "stm-Latn-PG": "stm", + "stn-Latn-SB": "stn", + "sto-Latn-CA": "sto", + "stp-Latn-MX": "stp", + "stq-Latn-DE": "stq", + "str-Latn-CA": "str", + "sts-Arab-AF": "sts", + "stt-Latn-VN": "stt", + "stv-Arab-ET": "stv-Arab", + "stv-Ethi-ET": "stv", + "stw-Latn-FM": "stw", + "sty-Cyrl-RU": "sty", + "su-Latn-ID": "su", + "su-Sund-ID": "su-Sund", + "sua-Latn-ZZ": "sua", + "sub-Latn-CD": "sub", + "suc-Latn-PH": "suc", + "sue-Latn-ZZ": "sue", + "sug-Latn-PG": "sug", + "sui-Latn-PG": "sui", + "suj-Latn-TZ": "suj", + "suk-Latn-TZ": "suk", + "suo-Latn-PG": "suo", + "suq-Ethi-ET": "suq-Ethi", + "suq-Latn-ET": "suq", + "sur-Latn-ZZ": "sur", + "sus-Latn-GN": "sus", + "sut-Latn-NI": "sut", + "suv-Beng-IN": "suv-Beng", + "suv-Deva-IN": "suv-Deva", + "suv-Latn-IN": "suv", + "suw-Latn-TZ": "suw", + "suy-Latn-BR": "suy", + "suz-Deva-NP": "suz", + "sv-Latn-AX": "sv-AX", + "sv-Latn-SE": "sv", + "sva-Cyrl-GE": "sva-Cyrl", + "sva-Geor-GE": "sva", + "sva-Latn-GE": "sva-Latn", + "svb-Latn-PG": "svb", + "svc-Latn-VC": "svc", + "sve-Latn-ID": "sve", + "svm-Latn-IT": "svm", + "svs-Latn-SB": "svs", + "sw-Latn-CD": "sw-CD", + "sw-Latn-KE": "sw-KE", + "sw-Latn-TZ": "sw", + "sw-Latn-UG": "sw-UG", + "swb-Arab-YT": "swb", + "swf-Latn-CD": "swf", + "swg-Latn-DE": "swg", + "swi-Hani-CN": "swi", + "swj-Latn-GA": "swj", + "swk-Latn-MW": "swk", + "swm-Latn-PG": "swm", + "swo-Latn-BR": "swo", + "swp-Latn-ZZ": "swp", + "swq-Latn-CM": "swq", + "swr-Latn-ID": "swr", + "sws-Latn-ID": "sws", + "swt-Latn-ID": "swt", + "swu-Latn-ID": "swu", + "swv-Deva-IN": "swv", + "sww-Latn-VU": "sww", + "swx-Latn-BR": "swx", + "swy-Latn-TD": "swy", + "sxb-Latn-KE": "sxb", + "sxe-Latn-GA": "sxe", + "sxn-Latn-ID": "sxn", + "sxr-Latn-TW": "sxr", + "sxs-Latn-NG": "sxs", + "sxu-Latn-DE": "sxu", + "sxu-Runr-DE": "sxu-Runr", + "sxw-Latn-ZZ": "sxw", + "sya-Latn-ID": "sya", + "syb-Latn-PH": "syb", + "syc-Syrc-TR": "syc", + "syi-Latn-GA": "syi", + "syk-Latn-NG": "syk", + "syl-Beng-BD": "syl", + "syl-Sylo-BD": "syl-Sylo", + "sym-Latn-BF": "sym", + "syn-Syrc-IR": "syn", + "syo-Latn-KH": "syo", + "syr-Syrc-IQ": "syr", + "sys-Latn-TD": "sys", + "syw-Deva-NP": "syw", + "syx-Latn-GA": "syx", + "sza-Latn-MY": "sza", + "szb-Latn-ID": "szb", + "szc-Latn-MY": "szc", + "szd-Latn-MY": "szd", + "szg-Latn-CD": "szg", + "szl-Latn-PL": "szl", + "szn-Latn-ID": "szn", + "szp-Latn-ID": "szp", + "szv-Latn-CM": "szv", + "szw-Latn-ID": "szw", + "szy-Latn-TW": "szy", + "ta-Taml-IN": "ta", + "taa-Latn-US": "taa", + "tab-Cyrl-RU": "tab", + "tac-Latn-MX": "tac", + "tad-Latn-ID": "tad", + "tae-Latn-BR": "tae", + "taf-Latn-BR": "taf", + "tag-Latn-SD": "tag", + "taj-Deva-NP": "taj", + "tak-Latn-NG": "tak", + "tal-Latn-ZZ": "tal", + "tan-Latn-ZZ": "tan", + "tao-Latn-TW": "tao", + "tap-Latn-CD": "tap", + "taq-Latn-ZZ": "taq", + "tar-Latn-MX": "tar", + "tas-Latn-VN": "tas", + "tau-Latn-US": "tau", + "tav-Latn-CO": "tav", + "taw-Latn-PG": "taw", + "tax-Latn-TD": "tax", + "tay-Hans-TW": "tay-Hans", + "tay-Hant-TW": "tay-Hant", + "tay-Latn-TW": "tay", + "taz-Latn-SD": "taz", + "tba-Latn-BR": "tba", + "tbc-Latn-ZZ": "tbc", + "tbd-Latn-ZZ": "tbd", + "tbe-Latn-SB": "tbe", + "tbf-Latn-ZZ": "tbf", + "tbg-Latn-ZZ": "tbg", + "tbh-Latn-AU": "tbh", + "tbi-Latn-SD": "tbi", + "tbj-Latn-PG": "tbj", + "tbk-Hano-PH": "tbk-Hano", + "tbk-Latn-PH": "tbk-Latn", + "tbk-Tagb-PH": "tbk", + "tbl-Latn-PH": "tbl", + "tbm-Latn-CD": "tbm", + "tbn-Latn-CO": "tbn", + "tbo-Latn-ZZ": "tbo", + "tbp-Latn-ID": "tbp", + "tbs-Latn-PG": "tbs", + "tbt-Latn-CD": "tbt", + "tbu-Latn-MX": "tbu", + "tbv-Latn-PG": "tbv", + "tbw-Latn-PH": "tbw", + "tbw-Tagb-PH": "tbw-Tagb", + "tbx-Latn-PG": "tbx", + "tby-Latn-ID": "tby", + "tbz-Latn-ZZ": "tbz", + "tca-Latn-BR": "tca", + "tcb-Latn-US": "tcb", + "tcc-Latn-TZ": "tcc", + "tcd-Latn-GH": "tcd", + "tce-Latn-CA": "tce", + "tcf-Latn-MX": "tcf", + "tcg-Latn-ID": "tcg", + "tch-Latn-TC": "tch", + "tci-Latn-ZZ": "tci", + "tck-Latn-GA": "tck", + "tcm-Latn-ID": "tcm", + "tcn-Tibt-NP": "tcn", + "tco-Mymr-MM": "tco", + "tcp-Latn-MM": "tcp", + "tcq-Latn-ID": "tcq", + "tcs-Latn-AU": "tcs", + "tcu-Latn-MX": "tcu", + "tcw-Latn-MX": "tcw", + "tcx-Taml-IN": "tcx", + "tcy-Knda-IN": "tcy", + "tcz-Latn-IN": "tcz", + "tda-Arab-NE": "tda-Arab", + "tda-Latn-NE": "tda-Latn", + "tda-Tfng-NE": "tda", + "tdb-Beng-IN": "tdb-Beng", + "tdb-Deva-IN": "tdb", + "tdb-Kthi-IN": "tdb-Kthi", + "tdc-Latn-CO": "tdc", + "tdd-Tale-CN": "tdd", + "tde-Latn-ML": "tde", + "tdg-Deva-NP": "tdg", + "tdh-Deva-NP": "tdh", + "tdi-Latn-ID": "tdi", + "tdj-Latn-ID": "tdj", + "tdk-Latn-NG": "tdk", + "tdl-Latn-NG": "tdl", + "tdm-Latn-GY": "tdm", + "tdn-Latn-ID": "tdn", + "tdo-Latn-NG": "tdo", + "tdq-Latn-NG": "tdq", + "tdr-Latn-VN": "tdr", + "tds-Latn-ID": "tds", + "tdt-Latn-TL": "tdt", + "tdv-Latn-NG": "tdv", + "tdx-Latn-MG": "tdx", + "tdy-Latn-PH": "tdy", + "te-Telu-IN": "te", + "tea-Latn-MY": "tea", + "teb-Latn-EC": "teb", + "tec-Latn-KE": "tec", + "ted-Latn-ZZ": "ted", + "tee-Latn-MX": "tee", + "teg-Latn-GA": "teg", + "teh-Latn-AR": "teh", + "tei-Latn-PG": "tei", + "tek-Latn-CD": "tek", + "tem-Latn-SL": "tem", + "ten-Latn-CO": "ten", + "teo-Latn-UG": "teo", + "tep-Latn-MX": "tep", + "teq-Latn-SD": "teq", + "ter-Latn-BR": "ter", + "tes-Java-ID": "tes", + "tet-Latn-TL": "tet", + "teu-Latn-UG": "teu", + "tev-Latn-ID": "tev", + "tew-Latn-US": "tew", + "tex-Latn-SS": "tex", + "tey-Latn-SD": "tey", + "tfi-Latn-ZZ": "tfi", + "tfn-Latn-US": "tfn", + "tfo-Latn-ID": "tfo", + "tfr-Latn-PA": "tfr", + "tft-Latn-ID": "tft", + "tg-Arab-PK": "tg-PK", + "tg-Cyrl-TJ": "tg", + "tga-Latn-KE": "tga", + "tgb-Latn-MY": "tgb", + "tgc-Latn-ZZ": "tgc", + "tgd-Latn-NG": "tgd", + "tge-Deva-NP": "tge", + "tgf-Tibt-BT": "tgf", + "tgh-Latn-TT": "tgh", + "tgi-Latn-PG": "tgi", + "tgj-Latn-IN": "tgj", + "tgn-Latn-PH": "tgn", + "tgo-Latn-ZZ": "tgo", + "tgp-Latn-VU": "tgp", + "tgq-Latn-MY": "tgq", + "tgs-Latn-VU": "tgs", + "tgt-Hano-PH": "tgt-Hano", + "tgt-Latn-PH": "tgt", + "tgt-Tagb-PH": "tgt-Tagb", + "tgu-Latn-ZZ": "tgu", + "tgv-Latn-BR": "tgv", + "tgw-Latn-CI": "tgw", + "tgx-Latn-CA": "tgx", + "tgy-Latn-SS": "tgy", + "tgz-Latn-AU": "tgz", + "th-Thai-TH": "th", + "thd-Latn-AU": "thd", + "the-Deva-NP": "the", + "thf-Deva-NP": "thf", + "thh-Latn-MX": "thh", + "thi-Tale-LA": "thi", + "thk-Latn-KE": "thk", + "thl-Deva-NP": "thl", + "thm-Thai-TH": "thm", + "thp-Dupl-CA": "thp-Dupl", + "thp-Latn-CA": "thp", + "thq-Deva-NP": "thq", + "thr-Deva-NP": "thr", + "ths-Deva-NP": "ths", + "tht-Latn-CA": "tht", + "thu-Latn-SS": "thu", + "thv-Arab-DZ": "thv-Arab", + "thv-Latn-DZ": "thv", + "thv-Tfng-DZ": "thv-Tfng", + "thy-Latn-NG": "thy", + "thz-Latn-NE": "thz", + "thz-Tfng-NE": "thz-Tfng", + "ti-Ethi-ER": "ti-ER", + "ti-Ethi-ET": "ti", + "tic-Latn-SD": "tic", + "tif-Latn-ZZ": "tif", + "tig-Ethi-ER": "tig", + "tih-Latn-MY": "tih", + "tii-Latn-CD": "tii", + "tij-Deva-NP": "tij", + "tik-Latn-ZZ": "tik", + "til-Latn-US": "til", + "tim-Latn-ZZ": "tim", + "tin-Cyrl-RU": "tin", + "tio-Latn-ZZ": "tio", + "tip-Latn-ID": "tip", + "tiq-Latn-BF": "tiq", + "tis-Latn-PH": "tis", + "tit-Latn-CO": "tit", + "tiu-Latn-PH": "tiu", + "tiv-Latn-NG": "tiv", + "tiw-Latn-AU": "tiw", + "tix-Latn-US": "tix", + "tiy-Latn-PH": "tiy", + "tja-Latn-LR": "tja", + "tjg-Latn-ID": "tjg", + "tji-Latn-CN": "tji", + "tjj-Latn-AU": "tjj", + "tjl-Mymr-MM": "tjl", + "tjn-Latn-CI": "tjn", + "tjo-Arab-DZ": "tjo", + "tjp-Latn-AU": "tjp", + "tjs-Latn-CN": "tjs", + "tju-Latn-AU": "tju", + "tjw-Latn-AU": "tjw", + "tk-Latn-AF": "tk-AF", + "tk-Latn-IR": "tk-IR", + "tk-Latn-TM": "tk", + "tka-Latn-BR": "tka", + "tkb-Deva-IN": "tkb", + "tkd-Latn-TL": "tkd", + "tke-Latn-MZ": "tke", + "tkf-Latn-BR": "tkf", + "tkg-Latn-MG": "tkg", + "tkl-Latn-TK": "tkl", + "tkp-Latn-SB": "tkp", + "tkq-Latn-NG": "tkq", + "tkr-Latn-AZ": "tkr", + "tks-Arab-IR": "tks", + "tkt-Deva-NP": "tkt", + "tku-Latn-MX": "tku", + "tkv-Latn-PG": "tkv", + "tkw-Latn-SB": "tkw", + "tkx-Latn-ID": "tkx", + "tkz-Latn-VN": "tkz", + "tla-Latn-MX": "tla", + "tlb-Latn-ID": "tlb", + "tlc-Latn-MX": "tlc", + "tld-Latn-ID": "tld", + "tlf-Latn-ZZ": "tlf", + "tlg-Latn-ID": "tlg", + "tli-Cyrl-US": "tli-Cyrl", + "tli-Latn-US": "tli", + "tlj-Latn-UG": "tlj", + "tlk-Latn-ID": "tlk", + "tll-Latn-CD": "tll", + "tlm-Latn-VU": "tlm", + "tln-Latn-ID": "tln", + "tlp-Latn-MX": "tlp", + "tlq-Latn-MM": "tlq", + "tlr-Latn-SB": "tlr", + "tls-Latn-VU": "tls", + "tlt-Latn-ID": "tlt", + "tlu-Latn-ID": "tlu", + "tlv-Latn-ID": "tlv", + "tlx-Latn-ZZ": "tlx", + "tly-Latn-AZ": "tly", + "tma-Latn-TD": "tma", + "tmb-Latn-VU": "tmb", + "tmc-Latn-TD": "tmc", + "tmd-Latn-PG": "tmd", + "tme-Latn-BR": "tme", + "tmf-Latn-PY": "tmf", + "tmg-Latn-ID": "tmg", + "tmh-Latn-NE": "tmh", + "tmi-Latn-VU": "tmi", + "tmj-Latn-ID": "tmj", + "tmk-Deva-NP": "tmk", + "tml-Latn-ID": "tml", + "tmm-Latn-VN": "tmm", + "tmn-Latn-ID": "tmn", + "tmo-Latn-MY": "tmo", + "tmq-Latn-PG": "tmq", + "tmr-Syrc-IL": "tmr", + "tmt-Latn-VU": "tmt", + "tmu-Latn-ID": "tmu", + "tmv-Latn-CD": "tmv", + "tmw-Latn-MY": "tmw", + "tmy-Latn-ZZ": "tmy", + "tmz-Latn-VE": "tmz", + "tn-Latn-ZA": "tn", + "tna-Latn-BO": "tna", + "tnb-Latn-CO": "tnb", + "tnc-Latn-CO": "tnc", + "tnd-Latn-CO": "tnd", + "tng-Latn-TD": "tng", + "tnh-Latn-ZZ": "tnh", + "tni-Latn-ID": "tni", + "tnk-Latn-VU": "tnk", + "tnl-Latn-VU": "tnl", + "tnm-Latn-ID": "tnm", + "tnn-Latn-VU": "tnn", + "tno-Latn-BO": "tno", + "tnp-Latn-VU": "tnp", + "tnq-Latn-PR": "tnq", + "tnr-Latn-SN": "tnr", + "tns-Latn-PG": "tns", + "tnt-Latn-ID": "tnt", + "tnv-Cakm-BD": "tnv", + "tnw-Latn-ID": "tnw", + "tnx-Latn-SB": "tnx", + "tny-Latn-TZ": "tny", + "to-Latn-TO": "to", + "tob-Latn-AR": "tob", + "toc-Latn-MX": "toc", + "tod-Latn-GN": "tod", + "tof-Latn-ZZ": "tof", + "tog-Latn-MW": "tog", + "toh-Latn-MZ": "toh", + "toi-Latn-ZM": "toi", + "toj-Latn-MX": "toj", + "tok-Latn-001": "tok", + "tol-Latn-US": "tol", + "tom-Latn-ID": "tom", + "too-Latn-MX": "too", + "top-Latn-MX": "top", + "toq-Latn-ZZ": "toq", + "tor-Latn-CD": "tor", + "tos-Latn-MX": "tos", + "tou-Latn-VN": "tou", + "tov-Arab-IR": "tov", + "tow-Latn-US": "tow", + "tox-Latn-PW": "tox", + "toy-Latn-ID": "toy", + "toz-Latn-CM": "toz", + "tpa-Latn-PG": "tpa", + "tpc-Latn-MX": "tpc", + "tpe-Beng-BD": "tpe-Beng", + "tpe-Latn-BD": "tpe", + "tpf-Latn-ID": "tpf", + "tpg-Latn-ID": "tpg", + "tpi-Latn-PG": "tpi", + "tpj-Latn-PY": "tpj", + "tpk-Latn-BR": "tpk", + "tpl-Latn-MX": "tpl", + "tpm-Latn-ZZ": "tpm", + "tpn-Latn-BR": "tpn", + "tpp-Latn-MX": "tpp", + "tpr-Latn-BR": "tpr", + "tpt-Latn-MX": "tpt", + "tpu-Khmr-KH": "tpu", + "tpv-Latn-MP": "tpv", + "tpx-Latn-MX": "tpx", + "tpy-Latn-BR": "tpy", + "tpz-Latn-ZZ": "tpz", + "tqb-Latn-BR": "tqb", + "tql-Latn-VU": "tql", + "tqm-Latn-PG": "tqm", + "tqn-Latn-US": "tqn", + "tqo-Latn-ZZ": "tqo", + "tqp-Latn-PG": "tqp", + "tqt-Latn-MX": "tqt", + "tqu-Latn-SB": "tqu", + "tqw-Latn-US": "tqw", + "tr-Latn-CY": "tr-CY", + "tr-Latn-TR": "tr", + "tra-Arab-AF": "tra", + "trb-Latn-PG": "trb", + "trc-Latn-MX": "trc", + "tre-Latn-ID": "tre", + "trf-Latn-TT": "trf", + "trg-Hebr-IL": "trg", + "trh-Latn-PG": "trh", + "tri-Latn-SR": "tri", + "trj-Latn-TD": "trj", + "trl-Latn-GB": "trl", + "trm-Arab-AF": "trm", + "trn-Latn-BO": "trn", + "tro-Latn-IN": "tro", + "trp-Beng-IN": "trp-Beng", + "trp-Latn-IN": "trp", + "trq-Latn-MX": "trq", + "trr-Latn-PE": "trr", + "trs-Latn-MX": "trs", + "trt-Latn-ID": "trt", + "tru-Latn-TR": "tru", + "trv-Latn-TW": "trv", + "trw-Arab-PK": "trw", + "trx-Latn-MY": "trx", + "try-Latn-IN": "try", + "trz-Latn-BR": "trz", + "ts-Latn-ZA": "ts", + "tsa-Latn-CG": "tsa", + "tsb-Latn-ET": "tsb", + "tsc-Latn-MZ": "tsc", + "tsd-Grek-GR": "tsd", + "tsg-Latn-PH": "tsg", + "tsh-Latn-CM": "tsh", + "tsi-Latn-CA": "tsi", + "tsj-Tibt-BT": "tsj", + "tsl-Latn-VN": "tsl", + "tsp-Latn-BF": "tsp", + "tsr-Latn-VU": "tsr", + "tst-Latn-ML": "tst", + "tsu-Latn-TW": "tsu", + "tsv-Latn-GA": "tsv", + "tsw-Latn-ZZ": "tsw", + "tsx-Latn-PG": "tsx", + "tsz-Latn-MX": "tsz", + "tt-Cyrl-RU": "tt", + "ttb-Latn-NG": "ttb", + "ttc-Latn-GT": "ttc", + "ttd-Latn-ZZ": "ttd", + "tte-Latn-ZZ": "tte", + "ttf-Latn-CM": "ttf", + "tth-Laoo-LA": "tth", + "tti-Latn-ID": "tti", + "ttj-Latn-UG": "ttj", + "ttk-Latn-CO": "ttk", + "ttl-Latn-ZM": "ttl", + "ttm-Latn-CA": "ttm", + "ttn-Latn-ID": "ttn", + "tto-Laoo-LA": "tto", + "ttp-Latn-ID": "ttp", + "ttr-Latn-ZZ": "ttr", + "tts-Thai-TH": "tts", + "ttt-Latn-AZ": "ttt", + "ttu-Latn-PG": "ttu", + "ttv-Latn-PG": "ttv", + "ttw-Latn-MY": "ttw", + "tty-Latn-ID": "tty", + "tua-Latn-PG": "tua", + "tub-Latn-US": "tub", + "tuc-Latn-PG": "tuc", + "tud-Latn-BR": "tud", + "tue-Latn-CO": "tue", + "tuf-Latn-CO": "tuf", + "tug-Latn-TD": "tug", + "tuh-Latn-ZZ": "tuh", + "tui-Latn-CM": "tui", + "tuj-Latn-ID": "tuj", + "tul-Latn-ZZ": "tul", + "tum-Latn-MW": "tum", + "tun-Latn-US": "tun", + "tuo-Latn-BR": "tuo", + "tuq-Latn-ZZ": "tuq", + "tus-Latn-CA": "tus", + "tuu-Latn-US": "tuu", + "tuv-Latn-KE": "tuv", + "tux-Latn-BR": "tux", + "tuy-Latn-KE": "tuy", + "tuz-Latn-BF": "tuz", + "tva-Latn-SB": "tva", + "tvd-Latn-ZZ": "tvd", + "tve-Latn-ID": "tve", + "tvk-Latn-VU": "tvk", + "tvl-Latn-TV": "tvl", + "tvm-Latn-ID": "tvm", + "tvn-Mymr-MM": "tvn", + "tvo-Latn-ID": "tvo", + "tvs-Latn-KE": "tvs", + "tvt-Latn-IN": "tvt", + "tvu-Latn-ZZ": "tvu", + "tvw-Latn-ID": "tvw", + "tvx-Latn-TW": "tvx", + "twa-Latn-US": "twa", + "twb-Latn-PH": "twb", + "twd-Latn-NL": "twd", + "twe-Latn-ID": "twe", + "twf-Latn-US": "twf", + "twg-Latn-ID": "twg", + "twh-Latn-ZZ": "twh", + "twl-Latn-MZ": "twl", + "twm-Deva-IN": "twm", + "twn-Latn-CM": "twn", + "two-Latn-BW": "two", + "twp-Latn-PG": "twp", + "twq-Latn-NE": "twq", + "twr-Latn-MX": "twr", + "twt-Latn-BR": "twt", + "twu-Latn-ID": "twu", + "tww-Latn-PG": "tww", + "twx-Latn-MZ": "twx", + "twy-Latn-ID": "twy", + "txa-Latn-MY": "txa", + "txe-Latn-ID": "txe", + "txg-Tang-CN": "txg", + "txi-Latn-BR": "txi", + "txj-Latn-NG": "txj", + "txm-Latn-ID": "txm", + "txn-Latn-ID": "txn", + "txo-Toto-IN": "txo", + "txq-Latn-ID": "txq", + "txs-Latn-ID": "txs", + "txt-Latn-ID": "txt", + "txu-Latn-BR": "txu", + "txx-Latn-MY": "txx", + "txy-Latn-MG": "txy", + "ty-Latn-PF": "ty", + "tya-Latn-ZZ": "tya", + "tye-Latn-NG": "tye", + "tyh-Latn-VN": "tyh", + "tyi-Latn-CG": "tyi", + "tyj-Latn-VN": "tyj", + "tyl-Latn-VN": "tyl", + "tyn-Latn-ID": "tyn", + "typ-Latn-AU": "typ", + "tyr-Tavt-VN": "tyr", + "tys-Latn-VN": "tys", + "tyt-Latn-VN": "tyt", + "tyt-Tavt-VN": "tyt-Tavt", + "tyu-Latn-BW": "tyu", + "tyv-Cyrl-RU": "tyv", + "tyx-Latn-CG": "tyx", + "tyy-Latn-NG": "tyy", + "tyz-Latn-VN": "tyz", + "tzh-Latn-MX": "tzh", + "tzj-Latn-GT": "tzj", + "tzl-Latn-001": "tzl", + "tzm-Latn-MA": "tzm", + "tzn-Latn-ID": "tzn", + "tzo-Latn-MX": "tzo", + "tzx-Latn-PG": "tzx", + "uam-Latn-BR": "uam", + "uar-Latn-PG": "uar", + "uba-Latn-NG": "uba", + "ubi-Latn-TD": "ubi", + "ubl-Latn-PH": "ubl", + "ubr-Latn-PG": "ubr", + "ubu-Latn-ZZ": "ubu", + "uda-Latn-NG": "uda", + "ude-Cyrl-RU": "ude", + "udg-Mlym-IN": "udg", + "udi-Aghb-RU": "udi", + "udj-Latn-ID": "udj", + "udl-Latn-CM": "udl", + "udm-Cyrl-RU": "udm", + "udu-Latn-SD": "udu", + "ues-Latn-ID": "ues", + "ufi-Latn-PG": "ufi", + "ug-Arab-CN": "ug", + "ug-Cyrl-KZ": "ug-KZ", + "ug-Cyrl-MN": "ug-MN", + "uga-Ugar-SY": "uga", + "ugb-Latn-AU": "ugb", + "uge-Latn-SB": "uge", + "ugh-Cyrl-RU": "ugh", + "ugo-Thai-TH": "ugo", + "uha-Latn-NG": "uha", + "uhn-Latn-ID": "uhn", + "uis-Latn-PG": "uis", + "uiv-Latn-CM": "uiv", + "uji-Latn-NG": "uji", + "uk-Cyrl-MD": "uk-MD", + "uk-Cyrl-SK": "uk-SK", + "uk-Cyrl-UA": "uk", + "uka-Latn-ID": "uka", + "ukg-Latn-PG": "ukg", + "ukh-Latn-CF": "ukh", + "uki-Orya-IN": "uki", + "ukk-Latn-MM": "ukk", + "ukp-Latn-NG": "ukp", + "ukq-Latn-NG": "ukq", + "uku-Latn-NG": "uku", + "ukv-Latn-SS": "ukv", + "ukw-Latn-NG": "ukw", + "uky-Latn-AU": "uky", + "ula-Latn-NG": "ula", + "ulb-Latn-NG": "ulb", + "ulc-Cyrl-RU": "ulc", + "ule-Latn-AR": "ule", + "ulf-Latn-ID": "ulf", + "uli-Latn-FM": "uli", + "ulk-Latn-AU": "ulk", + "ulm-Latn-ID": "ulm", + "uln-Latn-PG": "uln", + "ulu-Latn-ID": "ulu", + "ulw-Latn-NI": "ulw", + "uma-Latn-US": "uma", + "umb-Latn-AO": "umb", + "umd-Latn-AU": "umd", + "umg-Latn-AU": "umg", + "umi-Latn-MY": "umi", + "umm-Latn-NG": "umm", + "umn-Latn-MM": "umn", + "umo-Latn-BR": "umo", + "ump-Latn-AU": "ump", + "umr-Latn-AU": "umr", + "ums-Latn-ID": "ums", + "una-Latn-PG": "una", + "und-Cpmn-CY": "und-Cpmn", + "und-Latn-AQ": "und-AQ", + "und-Latn-BV": "und-BV", + "und-Latn-CP": "und-CP", + "und-Latn-GS": "und-GS", + "und-Latn-HM": "und-HM", + "une-Latn-NG": "une", + "ung-Latn-AU": "ung", + "uni-Latn-PG": "uni", + "unk-Latn-BR": "unk", + "unm-Latn-US": "unm", + "unn-Latn-AU": "unn", + "unr-Beng-IN": "unr", + "unr-Deva-NP": "unr-NP", + "unr-Nagm-IN": "unr-Nagm", + "unu-Latn-PG": "unu", + "unx-Beng-IN": "unx", + "unz-Latn-ID": "unz", + "uon-Latn-TW": "uon", + "upi-Latn-PG": "upi", + "upv-Latn-VU": "upv", + "ur-Arab-GB": "ur-GB", + "ur-Arab-IN": "ur-IN", + "ur-Arab-MU": "ur-MU", + "ur-Arab-PK": "ur", + "ura-Latn-PE": "ura", + "urb-Latn-BR": "urb", + "urc-Latn-AU": "urc", + "ure-Latn-BO": "ure", + "urf-Latn-AU": "urf", + "urg-Latn-PG": "urg", + "urh-Latn-NG": "urh", + "uri-Latn-ZZ": "uri", + "urk-Thai-TH": "urk", + "urm-Latn-PG": "urm", + "urn-Latn-ID": "urn", + "uro-Latn-PG": "uro", + "urp-Latn-BR": "urp", + "urr-Latn-VU": "urr", + "urt-Latn-ZZ": "urt", + "uru-Latn-BR": "uru", + "urv-Latn-PG": "urv", + "urw-Latn-ZZ": "urw", + "urx-Latn-PG": "urx", + "ury-Latn-ID": "ury", + "urz-Latn-BR": "urz", + "usa-Latn-ZZ": "usa", + "ush-Arab-PK": "ush", + "usi-Beng-BD": "usi-Beng", + "usi-Latn-BD": "usi", + "usk-Latn-CM": "usk", + "usp-Latn-GT": "usp", + "uss-Latn-NG": "uss", + "usu-Latn-PG": "usu", + "uta-Latn-NG": "uta", + "ute-Latn-US": "ute", + "uth-Latn-ZZ": "uth", + "utp-Latn-SB": "utp", + "utr-Latn-ZZ": "utr", + "utu-Latn-PG": "utu", + "uum-Cyrl-GE": "uum-Cyrl", + "uum-Grek-GE": "uum", + "uur-Latn-VU": "uur", + "uve-Latn-NC": "uve", + "uvh-Latn-ZZ": "uvh", + "uvl-Latn-ZZ": "uvl", + "uwa-Latn-AU": "uwa", + "uya-Latn-NG": "uya", + "uz-Arab-AF": "uz-AF", + "uz-Cyrl-CN": "uz-CN", + "uz-Latn-UZ": "uz", + "uzs-Arab-AF": "uzs", + "vaa-Taml-IN": "vaa", + "vae-Latn-CF": "vae", + "vaf-Arab-IR": "vaf", + "vag-Latn-ZZ": "vag", + "vah-Deva-IN": "vah", + "vai-Vaii-LR": "vai", + "vaj-Latn-NA": "vaj", + "val-Latn-PG": "val", + "vam-Latn-PG": "vam", + "van-Latn-ZZ": "van", + "vao-Latn-VU": "vao", + "vap-Latn-IN": "vap", + "var-Latn-MX": "var", + "vas-Deva-IN": "vas", + "vas-Gujr-IN": "vas-Gujr", + "vau-Latn-CD": "vau", + "vav-Deva-IN": "vav", + "vav-Gujr-IN": "vav-Gujr", + "vay-Deva-NP": "vay", + "vbb-Latn-ID": "vbb", + "vbk-Latn-PH": "vbk", + "ve-Latn-ZA": "ve", + "vec-Latn-IT": "vec", + "vem-Latn-NG": "vem", + "veo-Latn-US": "veo", + "vep-Latn-RU": "vep", + "ver-Latn-NG": "ver", + "vgr-Arab-PK": "vgr", + "vi-Latn-VN": "vi", + "vic-Latn-SX": "vic", + "vid-Latn-TZ": "vid", + "vif-Latn-CG": "vif", + "vig-Latn-BF": "vig", + "vil-Latn-AR": "vil", + "vin-Latn-TZ": "vin", + "vit-Latn-NG": "vit", + "viv-Latn-ZZ": "viv", + "vka-Latn-AU": "vka", + "vkj-Latn-TD": "vkj", + "vkk-Latn-ID": "vkk", + "vkl-Latn-ID": "vkl", + "vkm-Latn-BR": "vkm", + "vkn-Latn-NG": "vkn", + "vko-Latn-ID": "vko", + "vkp-Deva-IN": "vkp-Deva", + "vkp-Latn-IN": "vkp", + "vkt-Latn-ID": "vkt", + "vku-Latn-AU": "vku", + "vkz-Latn-NG": "vkz", + "vlp-Latn-VU": "vlp", + "vls-Latn-BE": "vls", + "vma-Latn-AU": "vma", + "vmb-Latn-AU": "vmb", + "vmc-Latn-MX": "vmc", + "vmd-Knda-IN": "vmd", + "vme-Latn-ID": "vme", + "vmf-Latn-DE": "vmf", + "vmg-Latn-PG": "vmg", + "vmh-Arab-IR": "vmh", + "vmi-Latn-AU": "vmi", + "vmj-Latn-MX": "vmj", + "vmk-Latn-MZ": "vmk", + "vml-Latn-AU": "vml", + "vmm-Latn-MX": "vmm", + "vmp-Latn-MX": "vmp", + "vmq-Latn-MX": "vmq", + "vmr-Latn-MZ": "vmr", + "vms-Latn-ID": "vms", + "vmu-Latn-AU": "vmu", + "vmw-Latn-MZ": "vmw", + "vmx-Latn-MX": "vmx", + "vmy-Latn-MX": "vmy", + "vmz-Latn-MX": "vmz", + "vnk-Latn-SB": "vnk", + "vnm-Latn-VU": "vnm", + "vnp-Latn-VU": "vnp", + "vo-Latn-001": "vo", + "vor-Latn-NG": "vor", + "vot-Latn-RU": "vot", + "vra-Latn-VU": "vra", + "vro-Latn-EE": "vro", + "vrs-Latn-SB": "vrs", + "vrt-Latn-VU": "vrt", + "vto-Latn-ID": "vto", + "vum-Latn-GA": "vum", + "vun-Latn-TZ": "vun", + "vut-Latn-ZZ": "vut", + "vwa-Latn-CN": "vwa", + "vwa-Mymr-CN": "vwa-Mymr", + "wa-Latn-BE": "wa", + "waa-Latn-US": "waa", + "wab-Latn-PG": "wab", + "wac-Latn-US": "wac", + "wad-Latn-ID": "wad", + "wae-Latn-CH": "wae", + "waf-Latn-BR": "waf", + "wag-Latn-PG": "wag", + "wah-Latn-ID": "wah", + "wai-Latn-ID": "wai", + "waj-Latn-ZZ": "waj", + "wal-Ethi-ET": "wal", + "wam-Latn-US": "wam", + "wan-Latn-ZZ": "wan", + "wap-Latn-GY": "wap", + "waq-Latn-AU": "waq", + "war-Latn-PH": "war", + "was-Latn-US": "was", + "wat-Latn-PG": "wat", + "wau-Latn-BR": "wau", + "wav-Latn-NG": "wav", + "waw-Latn-BR": "waw", + "wax-Latn-PG": "wax", + "way-Latn-SR": "way", + "waz-Latn-PG": "waz", + "wba-Latn-VE": "wba", + "wbb-Latn-ID": "wbb", + "wbe-Latn-ID": "wbe", + "wbf-Latn-BF": "wbf", + "wbh-Latn-TZ": "wbh", + "wbi-Latn-TZ": "wbi", + "wbj-Latn-TZ": "wbj", + "wbk-Arab-AF": "wbk", + "wbl-Arab-AF": "wbl-Arab", + "wbl-Cyrl-TJ": "wbl-Cyrl", + "wbl-Latn-PK": "wbl", + "wbm-Latn-CN": "wbm", + "wbp-Latn-AU": "wbp", + "wbq-Telu-IN": "wbq", + "wbr-Deva-IN": "wbr", + "wbt-Latn-AU": "wbt", + "wbv-Latn-AU": "wbv", + "wbw-Latn-ID": "wbw", + "wca-Latn-BR": "wca", + "wci-Latn-ZZ": "wci", + "wdd-Latn-GA": "wdd", + "wdg-Latn-PG": "wdg", + "wdj-Latn-AU": "wdj", + "wdk-Latn-AU": "wdk", + "wdt-Latn-CA": "wdt", + "wdu-Latn-AU": "wdu", + "wdy-Latn-AU": "wdy", + "wec-Latn-CI": "wec", + "wed-Latn-PG": "wed", + "weg-Latn-AU": "weg", + "weh-Latn-CM": "weh", + "wei-Latn-PG": "wei", + "wem-Latn-BJ": "wem", + "weo-Latn-ID": "weo", + "wep-Latn-DE": "wep", + "wer-Latn-ZZ": "wer", + "wes-Latn-CM": "wes", + "wet-Latn-ID": "wet", + "weu-Latn-MM": "weu", + "wew-Latn-ID": "wew", + "wfg-Latn-ID": "wfg", + "wga-Latn-AU": "wga", + "wgb-Latn-PG": "wgb", + "wgg-Latn-AU": "wgg", + "wgi-Latn-ZZ": "wgi", + "wgo-Latn-ID": "wgo", + "wgu-Latn-AU": "wgu", + "wgy-Latn-AU": "wgy", + "wha-Latn-ID": "wha", + "whg-Latn-ZZ": "whg", + "whk-Latn-ID": "whk", + "whu-Latn-ID": "whu", + "wib-Latn-ZZ": "wib", + "wic-Latn-US": "wic", + "wie-Latn-AU": "wie", + "wif-Latn-AU": "wif", + "wig-Latn-AU": "wig", + "wih-Latn-AU": "wih", + "wii-Latn-PG": "wii", + "wij-Latn-AU": "wij", + "wik-Latn-AU": "wik", + "wil-Latn-AU": "wil", + "wim-Latn-AU": "wim", + "win-Latn-US": "win", + "wir-Latn-BR": "wir", + "wiu-Latn-ZZ": "wiu", + "wiv-Latn-ZZ": "wiv", + "wiy-Latn-US": "wiy", + "wja-Latn-ZZ": "wja", + "wji-Latn-ZZ": "wji", + "wka-Latn-TZ": "wka", + "wkd-Latn-ID": "wkd", + "wkr-Latn-AU": "wkr", + "wkw-Latn-AU": "wkw", + "wky-Latn-AU": "wky", + "wla-Latn-PG": "wla", + "wlg-Latn-AU": "wlg", + "wlh-Latn-TL": "wlh", + "wli-Latn-ID": "wli", + "wlm-Latn-GB": "wlm", + "wlo-Arab-ID": "wlo", + "wlr-Latn-VU": "wlr", + "wls-Latn-WF": "wls", + "wlu-Latn-AU": "wlu", + "wlv-Latn-AR": "wlv", + "wlw-Latn-ID": "wlw", + "wlx-Latn-GH": "wlx", + "wma-Latn-NG": "wma", + "wmb-Latn-AU": "wmb", + "wmc-Latn-PG": "wmc", + "wmd-Latn-BR": "wmd", + "wme-Deva-NP": "wme", + "wmh-Latn-TL": "wmh", + "wmi-Latn-AU": "wmi", + "wmm-Latn-ID": "wmm", + "wmn-Latn-NC": "wmn", + "wmo-Latn-ZZ": "wmo", + "wms-Latn-ID": "wms", + "wmt-Latn-AU": "wmt", + "wmw-Arab-MZ": "wmw-Arab", + "wmw-Latn-MZ": "wmw", + "wmx-Latn-PG": "wmx", + "wnb-Latn-PG": "wnb", + "wnc-Latn-ZZ": "wnc", + "wnd-Latn-AU": "wnd", + "wne-Arab-PK": "wne", + "wng-Latn-ID": "wng", + "wni-Arab-KM": "wni", + "wnk-Latn-ID": "wnk", + "wnm-Latn-AU": "wnm", + "wnn-Latn-AU": "wnn", + "wno-Latn-ID": "wno", + "wnp-Latn-PG": "wnp", + "wnu-Latn-ZZ": "wnu", + "wnw-Latn-US": "wnw", + "wny-Latn-AU": "wny", + "wo-Latn-SN": "wo", + "woa-Latn-AU": "woa", + "wob-Latn-ZZ": "wob", + "woc-Latn-PG": "woc", + "wod-Latn-ID": "wod", + "woe-Latn-FM": "woe", + "wof-Arab-GM": "wof-Arab", + "wof-Latn-GM": "wof", + "wog-Latn-PG": "wog", + "woi-Latn-ID": "woi", + "wok-Latn-CM": "wok", + "wom-Latn-NG": "wom", + "won-Latn-CD": "won", + "woo-Latn-ID": "woo", + "wor-Latn-ID": "wor", + "wos-Latn-ZZ": "wos", + "wow-Latn-ID": "wow", + "wpc-Latn-VE": "wpc", + "wrb-Latn-AU": "wrb", + "wrg-Latn-AU": "wrg", + "wrh-Latn-AU": "wrh", + "wri-Latn-AU": "wri", + "wrk-Latn-AU": "wrk", + "wrl-Latn-AU": "wrl", + "wrm-Latn-AU": "wrm", + "wro-Latn-AU": "wro", + "wrp-Latn-ID": "wrp", + "wrr-Latn-AU": "wrr", + "wrs-Latn-ZZ": "wrs", + "wru-Latn-ID": "wru", + "wrv-Latn-PG": "wrv", + "wrw-Latn-AU": "wrw", + "wrx-Latn-ID": "wrx", + "wrz-Latn-AU": "wrz", + "wsa-Latn-ID": "wsa", + "wsg-Gong-IN": "wsg", + "wsi-Latn-VU": "wsi", + "wsk-Latn-ZZ": "wsk", + "wsr-Latn-PG": "wsr", + "wss-Latn-GH": "wss", + "wsu-Latn-BR": "wsu", + "wsv-Arab-AF": "wsv", + "wtf-Latn-PG": "wtf", + "wth-Latn-AU": "wth", + "wti-Latn-ET": "wti", + "wtk-Latn-PG": "wtk", + "wtm-Deva-IN": "wtm", + "wtw-Bugi-ID": "wtw-Bugi", + "wtw-Latn-ID": "wtw", + "wua-Latn-AU": "wua", + "wub-Latn-AU": "wub", + "wud-Latn-TG": "wud", + "wul-Latn-ID": "wul", + "wum-Latn-GA": "wum", + "wun-Latn-TZ": "wun", + "wur-Latn-AU": "wur", + "wut-Latn-PG": "wut", + "wuu-Hans-CN": "wuu", + "wuv-Latn-ZZ": "wuv", + "wux-Latn-AU": "wux", + "wuy-Latn-ID": "wuy", + "wwa-Latn-ZZ": "wwa", + "wwb-Latn-AU": "wwb", + "wwo-Latn-VU": "wwo", + "wwr-Latn-AU": "wwr", + "www-Latn-CM": "www", + "wxw-Latn-AU": "wxw", + "wyb-Latn-AU": "wyb", + "wyi-Latn-AU": "wyi", + "wym-Latn-PL": "wym", + "wyn-Latn-US": "wyn", + "wyr-Latn-BR": "wyr", + "wyy-Latn-FJ": "wyy", + "xaa-Latn-ES": "xaa", + "xab-Latn-NG": "xab", + "xai-Latn-BR": "xai", + "xaj-Latn-BR": "xaj", + "xak-Latn-VE": "xak", + "xal-Cyrl-RU": "xal", + "xam-Latn-ZA": "xam", + "xan-Ethi-ET": "xan", + "xao-Latn-VN": "xao", + "xar-Latn-PG": "xar", + "xas-Cyrl-RU": "xas", + "xat-Latn-BR": "xat", + "xau-Latn-ID": "xau", + "xav-Latn-BR": "xav", + "xaw-Latn-US": "xaw", + "xay-Latn-ID": "xay", + "xbb-Latn-AU": "xbb", + "xbd-Latn-AU": "xbd", + "xbe-Latn-AU": "xbe", + "xbg-Latn-AU": "xbg", + "xbi-Latn-ZZ": "xbi", + "xbj-Latn-AU": "xbj", + "xbm-Latn-FR": "xbm", + "xbn-Latn-MY": "xbn", + "xbp-Latn-AU": "xbp", + "xbr-Latn-ID": "xbr", + "xbw-Latn-BR": "xbw", + "xby-Latn-AU": "xby", + "xch-Latn-US": "xch", + "xco-Chrs-UZ": "xco", + "xcr-Cari-TR": "xcr", + "xda-Latn-AU": "xda", + "xdk-Latn-AU": "xdk", + "xdo-Latn-AO": "xdo", + "xdq-Cyrl-RU": "xdq", + "xdy-Latn-ID": "xdy", + "xed-Latn-CM": "xed", + "xeg-Latn-ZA": "xeg", + "xem-Latn-ID": "xem", + "xer-Latn-BR": "xer", + "xes-Latn-ZZ": "xes", + "xet-Latn-BR": "xet", + "xeu-Latn-PG": "xeu", + "xgb-Latn-CI": "xgb", + "xgd-Latn-AU": "xgd", + "xgg-Latn-AU": "xgg", + "xgi-Latn-AU": "xgi", + "xgm-Latn-AU": "xgm", + "xgu-Latn-AU": "xgu", + "xgw-Latn-AU": "xgw", + "xh-Latn-ZA": "xh", + "xhe-Arab-PK": "xhe", + "xhm-Khmr-KH": "xhm", + "xhv-Latn-VN": "xhv", + "xii-Latn-ZA": "xii", + "xin-Latn-GT": "xin", + "xir-Latn-BR": "xir", + "xis-Orya-IN": "xis", + "xiy-Latn-BR": "xiy", + "xjb-Latn-AU": "xjb", + "xjt-Latn-AU": "xjt", + "xka-Arab-PK": "xka", + "xkb-Latn-BJ": "xkb", + "xkc-Arab-IR": "xkc", + "xkd-Latn-ID": "xkd", + "xke-Latn-ID": "xke", + "xkg-Latn-ML": "xkg", + "xkj-Arab-IR": "xkj", + "xkl-Latn-ID": "xkl", + "xkn-Latn-ID": "xkn", + "xkp-Arab-IR": "xkp", + "xkq-Latn-ID": "xkq", + "xkr-Latn-BR": "xkr", + "xks-Latn-ID": "xks", + "xkt-Latn-GH": "xkt", + "xku-Latn-CG": "xku", + "xkv-Latn-BW": "xkv", + "xkw-Latn-ID": "xkw", + "xkx-Latn-PG": "xkx", + "xky-Latn-MY": "xky", + "xkz-Latn-BT": "xkz", + "xla-Latn-ZZ": "xla", + "xlc-Lyci-TR": "xlc", + "xld-Lydi-TR": "xld", + "xly-Elym-IR": "xly", + "xma-Latn-SO": "xma", + "xmb-Latn-CM": "xmb", + "xmc-Latn-MZ": "xmc", + "xmd-Latn-CM": "xmd", + "xmf-Geor-GE": "xmf", + "xmg-Latn-CM": "xmg", + "xmh-Latn-AU": "xmh", + "xmj-Latn-CM": "xmj", + "xmm-Latn-ID": "xmm", + "xmn-Mani-CN": "xmn", + "xmo-Latn-BR": "xmo", + "xmp-Latn-AU": "xmp", + "xmq-Latn-AU": "xmq", + "xmr-Merc-SD": "xmr", + "xmr-Mero-SD": "xmr-Mero", + "xmt-Latn-ID": "xmt", + "xmu-Latn-AU": "xmu", + "xmv-Latn-MG": "xmv", + "xmw-Latn-MG": "xmw", + "xmx-Latn-ID": "xmx", + "xmy-Latn-AU": "xmy", + "xmz-Latn-ID": "xmz", + "xna-Narb-SA": "xna", + "xnb-Latn-TW": "xnb", + "xni-Latn-AU": "xni", + "xnj-Latn-TZ": "xnj", + "xnk-Latn-AU": "xnk", + "xnm-Latn-AU": "xnm", + "xnn-Latn-PH": "xnn", + "xnq-Latn-MZ": "xnq", + "xnr-Deva-IN": "xnr", + "xnt-Latn-US": "xnt", + "xnu-Latn-AU": "xnu", + "xny-Latn-AU": "xny", + "xnz-Arab-EG": "xnz-Arab", + "xnz-Latn-EG": "xnz", + "xoc-Latn-NG": "xoc", + "xod-Latn-ID": "xod", + "xog-Latn-UG": "xog", + "xoi-Latn-PG": "xoi", + "xok-Latn-BR": "xok", + "xom-Ethi-ET": "xom-Ethi", + "xom-Latn-SD": "xom", + "xon-Latn-ZZ": "xon", + "xoo-Latn-BR": "xoo", + "xop-Latn-PG": "xop", + "xor-Latn-BR": "xor", + "xow-Latn-PG": "xow", + "xpa-Latn-AU": "xpa", + "xpb-Latn-AU": "xpb", + "xpd-Latn-AU": "xpd", + "xpf-Latn-AU": "xpf", + "xpg-Grek-TR": "xpg", + "xph-Latn-AU": "xph", + "xpi-Ogam-GB": "xpi", + "xpj-Latn-AU": "xpj", + "xpk-Latn-BR": "xpk", + "xpl-Latn-AU": "xpl", + "xpm-Cyrl-RU": "xpm", + "xpn-Latn-BR": "xpn", + "xpo-Latn-MX": "xpo", + "xpq-Latn-US": "xpq", + "xpr-Prti-IR": "xpr", + "xpt-Latn-AU": "xpt", + "xpv-Latn-AU": "xpv", + "xpw-Latn-AU": "xpw", + "xpx-Latn-AU": "xpx", + "xpz-Latn-AU": "xpz", + "xra-Latn-BR": "xra", + "xrb-Latn-ZZ": "xrb", + "xrd-Latn-AU": "xrd", + "xre-Latn-BR": "xre", + "xrg-Latn-AU": "xrg", + "xri-Latn-BR": "xri", + "xrm-Cyrl-RU": "xrm", + "xrn-Cyrl-RU": "xrn", + "xrr-Latn-IT": "xrr", + "xru-Latn-AU": "xru", + "xrw-Latn-PG": "xrw", + "xsa-Sarb-YE": "xsa", + "xsb-Latn-PH": "xsb", + "xse-Latn-ID": "xse", + "xsh-Latn-NG": "xsh", + "xsi-Latn-ZZ": "xsi", + "xsm-Latn-ZZ": "xsm", + "xsn-Latn-NG": "xsn", + "xsp-Latn-PG": "xsp", + "xsq-Latn-MZ": "xsq", + "xsr-Deva-NP": "xsr", + "xss-Cyrl-RU": "xss", + "xsu-Latn-VE": "xsu", + "xsy-Latn-TW": "xsy", + "xta-Latn-MX": "xta", + "xtb-Latn-MX": "xtb", + "xtc-Latn-SD": "xtc", + "xtd-Latn-MX": "xtd", + "xte-Latn-ID": "xte", + "xth-Latn-AU": "xth", + "xti-Latn-MX": "xti", + "xtj-Latn-MX": "xtj", + "xtl-Latn-MX": "xtl", + "xtm-Latn-MX": "xtm", + "xtn-Latn-MX": "xtn", + "xtp-Latn-MX": "xtp", + "xts-Latn-MX": "xts", + "xtt-Latn-MX": "xtt", + "xtu-Latn-MX": "xtu", + "xtv-Latn-AU": "xtv", + "xtw-Latn-BR": "xtw", + "xty-Latn-MX": "xty", + "xub-Knda-IN": "xub-Knda", + "xub-Mlym-IN": "xub-Mlym", + "xub-Taml-IN": "xub", + "xud-Latn-AU": "xud", + "xuj-Taml-IN": "xuj", + "xul-Latn-AU": "xul", + "xum-Ital-IT": "xum-Ital", + "xum-Latn-IT": "xum", + "xun-Latn-AU": "xun", + "xuo-Latn-TD": "xuo", + "xut-Latn-AU": "xut", + "xuu-Latn-NA": "xuu", + "xve-Ital-IT": "xve", + "xvi-Arab-AF": "xvi", + "xvn-Latn-ES": "xvn", + "xvo-Latn-IT": "xvo", + "xvs-Latn-IT": "xvs", + "xwa-Latn-BR": "xwa", + "xwd-Latn-AU": "xwd", + "xwe-Latn-ZZ": "xwe", + "xwj-Latn-AU": "xwj", + "xwk-Latn-AU": "xwk", + "xwl-Latn-BJ": "xwl", + "xwo-Cyrl-RU": "xwo", + "xwr-Latn-ID": "xwr", + "xwt-Latn-AU": "xwt", + "xww-Latn-AU": "xww", + "xxb-Latn-GH": "xxb", + "xxk-Latn-ID": "xxk", + "xxm-Latn-AU": "xxm", + "xxr-Latn-BR": "xxr", + "xxt-Latn-ID": "xxt", + "xya-Latn-AU": "xya", + "xyb-Latn-AU": "xyb", + "xyj-Latn-AU": "xyj", + "xyk-Latn-AU": "xyk", + "xyl-Latn-BR": "xyl", + "xyt-Latn-AU": "xyt", + "xyy-Latn-AU": "xyy", + "xzh-Marc-CN": "xzh", + "xzp-Latn-MX": "xzp", + "yaa-Latn-PE": "yaa", + "yab-Latn-BR": "yab", + "yac-Latn-ID": "yac", + "yad-Latn-PE": "yad", + "yae-Latn-VE": "yae", + "yaf-Latn-CD": "yaf", + "yag-Latn-CL": "yag", + "yai-Cyrl-TJ": "yai", + "yaj-Latn-CF": "yaj", + "yak-Latn-US": "yak", + "yal-Arab-GN": "yal-Arab", + "yal-Latn-GN": "yal", + "yam-Latn-ZZ": "yam", + "yan-Latn-NI": "yan", + "yao-Latn-MZ": "yao", + "yap-Latn-FM": "yap", + "yaq-Latn-MX": "yaq", + "yar-Latn-VE": "yar", + "yas-Latn-ZZ": "yas", + "yat-Latn-ZZ": "yat", + "yau-Latn-VE": "yau", + "yav-Latn-CM": "yav", + "yaw-Latn-BR": "yaw", + "yax-Latn-AO": "yax", + "yay-Latn-ZZ": "yay", + "yaz-Latn-ZZ": "yaz", + "yba-Latn-ZZ": "yba", + "ybb-Latn-CM": "ybb", + "ybe-Latn-CN": "ybe", + "ybe-Ougr-CN": "ybe-Ougr", + "ybh-Deva-NP": "ybh", + "ybi-Deva-NP": "ybi", + "ybj-Latn-NG": "ybj", + "ybl-Latn-NG": "ybl", + "ybm-Latn-PG": "ybm", + "ybn-Latn-BR": "ybn", + "ybo-Latn-PG": "ybo", + "ybx-Latn-PG": "ybx", + "yby-Latn-ZZ": "yby", + "ycl-Latn-CN": "ycl", + "ycn-Latn-CO": "ycn", + "yda-Latn-AU": "yda", + "yde-Latn-PG": "yde", + "ydg-Arab-PK": "ydg", + "ydk-Latn-PG": "ydk", + "yea-Knda-IN": "yea-Knda", + "yea-Mlym-IN": "yea", + "yec-Latn-DE": "yec", + "yee-Latn-PG": "yee", + "yei-Latn-CM": "yei", + "yej-Grek-IL": "yej", + "yel-Latn-CD": "yel", + "yer-Latn-ZZ": "yer", + "yes-Latn-NG": "yes", + "yet-Latn-ID": "yet", + "yeu-Telu-IN": "yeu", + "yev-Latn-PG": "yev", + "yey-Latn-BW": "yey", + "yga-Latn-AU": "yga", + "ygi-Latn-AU": "ygi", + "ygl-Latn-PG": "ygl", + "ygm-Latn-PG": "ygm", + "ygp-Plrd-CN": "ygp", + "ygr-Latn-ZZ": "ygr", + "ygu-Latn-AU": "ygu", + "ygw-Latn-ZZ": "ygw", + "yhd-Hebr-IL": "yhd", + "yi-Hebr-001": "yi", + "yi-Hebr-SE": "yi-SE", + "yi-Hebr-UA": "yi-UA", + "yi-Hebr-US": "yi-US", + "yia-Latn-AU": "yia", + "yig-Yiii-CN": "yig", + "yih-Hebr-DE": "yih", + "yii-Latn-AU": "yii", + "yij-Latn-AU": "yij", + "yil-Latn-AU": "yil", + "yim-Latn-IN": "yim", + "yir-Latn-ID": "yir", + "yis-Latn-PG": "yis", + "yiv-Yiii-CN": "yiv", + "yka-Arab-PH": "yka-Arab", + "yka-Latn-PH": "yka", + "ykg-Cyrl-RU": "ykg", + "yki-Latn-ID": "yki", + "ykk-Latn-PG": "ykk", + "ykm-Latn-PG": "ykm", + "yko-Latn-ZZ": "yko", + "ykr-Latn-PG": "ykr", + "yky-Latn-CF": "yky", + "yla-Latn-PG": "yla", + "ylb-Latn-PG": "ylb", + "yle-Latn-ZZ": "yle", + "ylg-Latn-ZZ": "ylg", + "yli-Latn-ID": "yli", + "yll-Latn-ZZ": "yll", + "ylr-Latn-AU": "ylr", + "ylu-Latn-PG": "ylu", + "yly-Latn-NC": "yly", + "ymb-Latn-PG": "ymb", + "yme-Latn-PE": "yme", + "ymg-Latn-CD": "ymg", + "ymk-Arab-MZ": "ymk-Arab", + "ymk-Latn-MZ": "ymk", + "yml-Latn-ZZ": "yml", + "ymm-Latn-SO": "ymm", + "ymn-Latn-ID": "ymn", + "ymo-Latn-PG": "ymo", + "ymp-Latn-PG": "ymp", + "yna-Plrd-CN": "yna", + "ynd-Latn-AU": "ynd", + "yng-Latn-CD": "yng", + "ynk-Cyrl-RU": "ynk", + "ynl-Latn-PG": "ynl", + "ynq-Latn-NG": "ynq", + "yns-Latn-CD": "yns", + "ynu-Latn-CO": "ynu", + "yo-Latn-NG": "yo", + "yob-Latn-PG": "yob", + "yog-Latn-PH": "yog", + "yoi-Jpan-JP": "yoi", + "yok-Latn-US": "yok", + "yol-Latn-GB": "yol", + "yom-Latn-CD": "yom", + "yon-Latn-ZZ": "yon", + "yot-Latn-NG": "yot", + "yoy-Thai-TH": "yoy", + "yra-Latn-PG": "yra", + "yrb-Latn-ZZ": "yrb", + "yre-Latn-ZZ": "yre", + "yrk-Cyrl-RU": "yrk", + "yrl-Latn-BR": "yrl", + "yrm-Latn-AU": "yrm", + "yro-Latn-BR": "yro", + "yrs-Latn-ID": "yrs", + "yrw-Latn-PG": "yrw", + "yry-Latn-AU": "yry", + "ysd-Yiii-CN": "ysd", + "ysn-Yiii-CN": "ysn", + "ysp-Yiii-CN": "ysp", + "ysr-Cyrl-RU": "ysr", + "yss-Latn-ZZ": "yss", + "ysy-Plrd-CN": "ysy", + "ytw-Latn-PG": "ytw", + "yty-Latn-AU": "yty", + "yua-Latn-MX": "yua", + "yub-Latn-AU": "yub", + "yuc-Latn-US": "yuc", + "yud-Hebr-IL": "yud", + "yue-Hans-CN": "yue-CN", + "yue-Hant-CA": "yue-CA", + "yue-Hant-HK": "yue", + "yuf-Latn-US": "yuf", + "yug-Cyrl-RU": "yug", + "yui-Latn-CO": "yui", + "yuj-Latn-ZZ": "yuj", + "yul-Latn-CF": "yul", + "yum-Latn-US": "yum", + "yun-Latn-NG": "yun", + "yup-Latn-CO": "yup", + "yuq-Latn-BO": "yuq", + "yur-Latn-US": "yur", + "yut-Latn-ZZ": "yut", + "yuw-Latn-ZZ": "yuw", + "yux-Cyrl-RU": "yux", + "yuz-Latn-BO": "yuz", + "yva-Latn-ID": "yva", + "yvt-Latn-VE": "yvt", + "ywa-Latn-PG": "ywa", + "ywg-Latn-AU": "ywg", + "ywn-Latn-BR": "ywn", + "ywq-Plrd-CN": "ywq", + "ywq-Yiii-CN": "ywq-Yiii", + "ywr-Latn-AU": "ywr", + "ywu-Plrd-CN": "ywu", + "ywu-Yiii-CN": "ywu-Yiii", + "yww-Latn-AU": "yww", + "yxa-Latn-AU": "yxa", + "yxg-Latn-AU": "yxg", + "yxl-Latn-AU": "yxl", + "yxm-Latn-AU": "yxm", + "yxu-Latn-AU": "yxu", + "yxy-Latn-AU": "yxy", + "yyr-Latn-AU": "yyr", + "yyu-Latn-PG": "yyu", + "za-Latn-CN": "za", + "zaa-Latn-MX": "zaa", + "zab-Latn-MX": "zab", + "zac-Latn-MX": "zac", + "zad-Latn-MX": "zad", + "zae-Latn-MX": "zae", + "zaf-Latn-MX": "zaf", + "zag-Latn-SD": "zag", + "zah-Latn-NG": "zah", + "zaj-Latn-TZ": "zaj", + "zak-Latn-TZ": "zak", + "zam-Latn-MX": "zam", + "zao-Latn-MX": "zao", + "zap-Latn-MX": "zap", + "zaq-Latn-MX": "zaq", + "zar-Latn-MX": "zar", + "zas-Latn-MX": "zas", + "zat-Latn-MX": "zat", + "zau-Arab-IN": "zau-Arab", + "zau-Tibt-IN": "zau", + "zav-Latn-MX": "zav", + "zaw-Latn-MX": "zaw", + "zax-Latn-MX": "zax", + "zay-Ethi-ET": "zay-Ethi", + "zay-Latn-ET": "zay", + "zaz-Latn-NG": "zaz", + "zba-Arab-001": "zba", + "zbc-Latn-MY": "zbc", + "zbe-Latn-MY": "zbe", + "zbt-Latn-ID": "zbt", + "zbu-Latn-NG": "zbu", + "zbw-Latn-MY": "zbw", + "zca-Latn-MX": "zca", + "zch-Hani-CN": "zch", + "zdj-Arab-KM": "zdj", + "zea-Latn-NL": "zea", + "zeg-Latn-PG": "zeg", + "zeh-Hani-CN": "zeh", + "zen-Arab-MR": "zen-Arab", + "zen-Tfng-MR": "zen", + "zga-Latn-TZ": "zga", + "zgb-Hani-CN": "zgb", + "zgh-Tfng-MA": "zgh", + "zgm-Hani-CN": "zgm", + "zgn-Hani-CN": "zgn", + "zgr-Latn-PG": "zgr", + "zh-Bopo-TW": "zh-Bopo", + "zh-Hanb-TW": "zh-Hanb", + "zh-Hani-CN": "zh-Hani", + "zh-Hans-CN": "zh", + "zh-Hant-AU": "zh-AU", + "zh-Hant-BN": "zh-BN", + "zh-Hant-GB": "zh-GB", + "zh-Hant-GF": "zh-GF", + "zh-Hant-HK": "zh-HK", + "zh-Hant-ID": "zh-ID", + "zh-Hant-MO": "zh-MO", + "zh-Hant-PA": "zh-PA", + "zh-Hant-PF": "zh-PF", + "zh-Hant-PH": "zh-PH", + "zh-Hant-SR": "zh-SR", + "zh-Hant-TH": "zh-TH", + "zh-Hant-TW": "zh-TW", + "zh-Hant-US": "zh-US", + "zh-Hant-VN": "zh-VN", + "zhd-Hani-CN": "zhd", + "zhd-Latn-VN": "zhd-Latn", + "zhi-Latn-NG": "zhi", + "zhn-Hani-CN": "zhn-Hani", + "zhn-Latn-CN": "zhn", + "zhw-Latn-CM": "zhw", + "zhx-Nshu-CN": "zhx", + "zia-Latn-ZZ": "zia", + "zik-Latn-PG": "zik", + "zil-Latn-GN": "zil", + "zim-Latn-TD": "zim", + "zin-Latn-TZ": "zin", + "ziw-Latn-TZ": "ziw", + "ziz-Latn-NG": "ziz", + "zka-Latn-ID": "zka", + "zkb-Cyrl-RU": "zkb", + "zkd-Latn-MM": "zkd", + "zko-Cyrl-RU": "zko", + "zkp-Latn-BR": "zkp", + "zkt-Kits-CN": "zkt", + "zku-Latn-AU": "zku", + "zkz-Cyrl-RU": "zkz", + "zla-Latn-CD": "zla", + "zlj-Hani-CN": "zlj", + "zlj-Latn-CN": "zlj-Latn", + "zlm-Latn-TG": "zlm", + "zln-Hani-CN": "zln", + "zlq-Hani-CN": "zlq", + "zma-Latn-AU": "zma", + "zmb-Latn-CD": "zmb", + "zmc-Latn-AU": "zmc", + "zmd-Latn-AU": "zmd", + "zme-Latn-AU": "zme", + "zmf-Latn-CD": "zmf", + "zmg-Latn-AU": "zmg", + "zmh-Latn-PG": "zmh", + "zmi-Latn-MY": "zmi", + "zmj-Latn-AU": "zmj", + "zmk-Latn-AU": "zmk", + "zml-Latn-AU": "zml", + "zmm-Latn-AU": "zmm", + "zmn-Latn-GA": "zmn", + "zmo-Latn-SD": "zmo", + "zmp-Latn-CD": "zmp", + "zmq-Latn-CD": "zmq", + "zmr-Latn-AU": "zmr", + "zms-Latn-CD": "zms", + "zmt-Latn-AU": "zmt", + "zmu-Latn-AU": "zmu", + "zmv-Latn-AU": "zmv", + "zmw-Latn-CD": "zmw", + "zmx-Latn-CG": "zmx", + "zmy-Latn-AU": "zmy", + "zmz-Latn-CD": "zmz", + "zna-Latn-TD": "zna", + "zne-Latn-ZZ": "zne", + "zng-Latn-VN": "zng", + "znk-Latn-AU": "znk", + "zns-Latn-NG": "zns", + "zoc-Latn-MX": "zoc", + "zoh-Latn-MX": "zoh", + "zom-Latn-IN": "zom", + "zoo-Latn-MX": "zoo", + "zoq-Latn-MX": "zoq", + "zor-Latn-MX": "zor", + "zos-Latn-MX": "zos", + "zpa-Latn-MX": "zpa", + "zpb-Latn-MX": "zpb", + "zpc-Latn-MX": "zpc", + "zpd-Latn-MX": "zpd", + "zpe-Latn-MX": "zpe", + "zpf-Latn-MX": "zpf", + "zpg-Latn-MX": "zpg", + "zph-Latn-MX": "zph", + "zpi-Latn-MX": "zpi", + "zpj-Latn-MX": "zpj", + "zpk-Latn-MX": "zpk", + "zpl-Latn-MX": "zpl", + "zpm-Latn-MX": "zpm", + "zpn-Latn-MX": "zpn", + "zpo-Latn-MX": "zpo", + "zpp-Latn-MX": "zpp", + "zpq-Latn-MX": "zpq", + "zpr-Latn-MX": "zpr", + "zps-Latn-MX": "zps", + "zpt-Latn-MX": "zpt", + "zpu-Latn-MX": "zpu", + "zpv-Latn-MX": "zpv", + "zpw-Latn-MX": "zpw", + "zpx-Latn-MX": "zpx", + "zpy-Latn-MX": "zpy", + "zpz-Latn-MX": "zpz", + "zqe-Hani-CN": "zqe", + "zqe-Latn-CN": "zqe-Latn", + "zrn-Latn-TD": "zrn", + "zro-Latn-EC": "zro", + "zrp-Hebr-FR": "zrp", + "zrs-Latn-ID": "zrs", + "zsa-Latn-PG": "zsa", + "zsr-Latn-MX": "zsr", + "zsu-Latn-PG": "zsu", + "zte-Latn-MX": "zte", + "ztg-Latn-MX": "ztg", + "ztl-Latn-MX": "ztl", + "ztm-Latn-MX": "ztm", + "ztn-Latn-MX": "ztn", + "ztp-Latn-MX": "ztp", + "ztq-Latn-MX": "ztq", + "zts-Latn-MX": "zts", + "ztt-Latn-MX": "ztt", + "ztu-Latn-MX": "ztu", + "ztx-Latn-MX": "ztx", + "zty-Latn-MX": "zty", + "zu-Latn-ZA": "zu", + "zua-Latn-NG": "zua", + "zuh-Latn-PG": "zuh", + "zum-Arab-OM": "zum", + "zun-Latn-US": "zun", + "zuy-Latn-CM": "zuy", + "zyg-Hani-CN": "zyg", + "zyj-Hani-CN": "zyj-Hani", + "zyj-Latn-CN": "zyj", + "zyn-Hani-CN": "zyn", + "zyp-Latn-MM": "zyp", + "zza-Latn-TR": "zza", + "zzj-Hani-CN": "zzj", +}; + +for (let [tag, maximal] of Object.entries(maxLikelySubtags)) { + assertEq(new Intl.Locale(tag).maximize().toString(), maximal); +} + +for (let [tag, minimal] of Object.entries(minLikelySubtags)) { + assertEq(new Intl.Locale(tag).minimize().toString(), minimal); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/Locale/likely-subtags.js b/js/src/tests/non262/Intl/Locale/likely-subtags.js new file mode 100644 index 0000000000..3b3e4bd905 --- /dev/null +++ b/js/src/tests/non262/Intl/Locale/likely-subtags.js @@ -0,0 +1,61 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')) + +var testDataMaximal = { + // Keeps "und" primary language. + "und-AQ": "und-Latn-AQ", + + // Modifies primary language. + "und-Cyrl-RO": "bg-Cyrl-RO", +} + +var testDataMinimal = { + // Undefined primary language. + "und": "en", + "und-Thai": "th", + "und-419": "es-419", + "und-150": "ru", + "und-AT": "de-AT", + + // https://ssl.icu-project.org/trac/ticket/13786 + "aae-Latn-IT": "aae", + "aae-Thai-CO": "aae-Thai-CO", + + // https://ssl.icu-project.org/trac/ticket/10220 + // https://ssl.icu-project.org/trac/ticket/12345 + "und-CW": "pap", + "und-US": "en", + "zh-Hant": "zh-TW", + "zh-Hani": "zh-Hani", +}; + +// Add variants, extensions, and privateuse subtags and ensure they don't +// modify the result of the likely subtags algorithms. +var extras = [ + "fonipa", + "a-not-assigned", + "u-attr", + "u-co", + "u-co-phonebk", + "x-private", +]; + +for (var [tag, maximal] of Object.entries(testDataMaximal)) { + assertEq(new Intl.Locale(tag).maximize().toString(), maximal); + assertEq(new Intl.Locale(maximal).maximize().toString(), maximal); + + for (var extra of extras) { + assertEq(new Intl.Locale(tag + "-" + extra).maximize().toString(), maximal + "-" + extra); + } +} + +for (var [tag, minimal] of Object.entries(testDataMinimal)) { + assertEq(new Intl.Locale(tag).minimize().toString(), minimal); + assertEq(new Intl.Locale(minimal).minimize().toString(), minimal); + + for (var extra of extras) { + assertEq(new Intl.Locale(tag + "-" + extra).minimize().toString(), minimal + "-" + extra); + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/Locale/same-compartment.js b/js/src/tests/non262/Intl/Locale/same-compartment.js new file mode 100644 index 0000000000..fb71c85f6c --- /dev/null +++ b/js/src/tests/non262/Intl/Locale/same-compartment.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')||!this.wrapWithProto) + +var tag = "de-Latn-AT-u-ca-gregory-nu-latn-co-phonebk-kf-false-kn-hc-h23"; +var locale = new Intl.Locale(tag); +var scwLocale = wrapWithProto(locale, Intl.Locale.prototype); + +for (var [key, {get, value = get}] of Object.entries(Object.getOwnPropertyDescriptors(Intl.Locale.prototype))) { + if (typeof value === "function") { + if (key !== "constructor") { + var expectedValue = value.call(locale); + + if (typeof expectedValue === "string" || typeof expectedValue === "boolean") { + assertEq(value.call(scwLocale), expectedValue, key); + } else if (expectedValue instanceof Intl.Locale) { + assertEq(value.call(scwLocale).toString(), expectedValue.toString(), key); + } else { + throw new Error("unexpected result value"); + } + } else { + assertEq(new value(scwLocale).toString(), new value(locale).toString(), key); + } + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/Locale/shell.js b/js/src/tests/non262/Intl/Locale/shell.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Intl/Locale/surface.js b/js/src/tests/non262/Intl/Locale/surface.js new file mode 100644 index 0000000000..ba90182436 --- /dev/null +++ b/js/src/tests/non262/Intl/Locale/surface.js @@ -0,0 +1,98 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')) + +function assertProperty(object, name, desc) { + assertEq(desc === undefined || (typeof desc === "object" && desc !== null), true, + "desc is a property descriptor"); + + var actual = Object.getOwnPropertyDescriptor(object, name); + if (desc === undefined) { + assertEq(actual, desc, `property ${String(name)} is absent`); + return; + } + assertEq(actual !== undefined, true, `property ${String(name)} is present`); + + var fields = ["value", "writable", "enumerable", "configurable", "get", "set"]; + for (var field of fields) { + if (Object.prototype.hasOwnProperty.call(desc, field)) { + assertEq(actual[field], desc[field], `unexpected value for ${field}`); + } + } +} + +function assertBuiltinFunction(fn, length, name) { + assertProperty(fn, "length", { + value: length, writable: false, enumerable: false, configurable: true, + }); +} + +function assertBuiltinMethod(object, propName, length, name) { + var desc = Object.getOwnPropertyDescriptor(object, propName); + assertProperty(object, propName, { + value: desc.value, writable: true, enumerable: false, configurable: true + }); + assertBuiltinFunction(desc.value, length, name); +} + +function assertBuiltinGetter(object, propName, length, name) { + var desc = Object.getOwnPropertyDescriptor(object, propName); + + assertBuiltinFunction(desc.get, length, name); +} + +// Intl.Locale( tag[, options] ) +assertBuiltinFunction(Intl.Locale, 1, "Locale"); + +// Properties of the Intl.Locale Constructor + +// Intl.Locale.prototype +assertProperty(Intl.Locale, "prototype", { + value: Intl.Locale.prototype, writable: false, enumerable: false, configurable: false, +}); + +// Properties of the Intl.Locale Prototype Object + +// Intl.Locale.prototype.constructor +assertProperty(Intl.Locale.prototype, "constructor", { + value: Intl.Locale, writable: true, enumerable: false, configurable: true, +}); + +// Intl.Locale.prototype[ @@toStringTag ] +assertProperty(Intl.Locale.prototype, Symbol.toStringTag, { + value: "Intl.Locale", writable: false, enumerable: false, configurable: true, +}); + +// Intl.Locale.prototype.toString () +assertBuiltinMethod(Intl.Locale.prototype, "toString", 0, "toString"); + +// get Intl.Locale.prototype.baseName +assertBuiltinGetter(Intl.Locale.prototype, "baseName", 0, "get baseName"); + +// get Intl.Locale.prototype.calendar +assertBuiltinGetter(Intl.Locale.prototype, "calendar", 0, "get calendar"); + +// get Intl.Locale.prototype.collation +assertBuiltinGetter(Intl.Locale.prototype, "collation", 0, "get collation"); + +// get Intl.Locale.prototype.hourCycle +assertBuiltinGetter(Intl.Locale.prototype, "hourCycle", 0, "get hourCycle"); + +// get Intl.Locale.prototype.caseFirst +assertBuiltinGetter(Intl.Locale.prototype, "caseFirst", 0, "get caseFirst"); + +// get Intl.Locale.prototype.numeric +assertBuiltinGetter(Intl.Locale.prototype, "numeric", 0, "get numeric"); + +// get Intl.Locale.prototype.numberingSystem +assertBuiltinGetter(Intl.Locale.prototype, "numberingSystem", 0, "get numberingSystem"); + +// get Intl.Locale.prototype.language +assertBuiltinGetter(Intl.Locale.prototype, "language", 0, "get language"); + +// get Intl.Locale.prototype.script +assertBuiltinGetter(Intl.Locale.prototype, "script", 0, "get script"); + +// get Intl.Locale.prototype.region +assertBuiltinGetter(Intl.Locale.prototype, "region", 0, "get region"); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/NumberFormat/StringBuffer.js b/js/src/tests/non262/Intl/NumberFormat/StringBuffer.js new file mode 100644 index 0000000000..70aaa7bd75 --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/StringBuffer.js @@ -0,0 +1,37 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// The implementation of the format function uses the C++ StringBuffer class, +// which changes its storage model at 32 characters, and uses it in a way which +// also means that there's no room for null-termination at this limit. +// This test makes sure that none of this affects the output. + +var format = new Intl.NumberFormat("it-IT", {minimumFractionDigits: 1}); + +assertEq(format.format(1123123123123123123123.1), "1.123.123.123.123.123.100.000,0"); +assertEq(format.format(12123123123123123123123.1), "12.123.123.123.123.122.000.000,0"); +assertEq(format.format(123123123123123123123123.1), "123.123.123.123.123.120.000.000,0"); + +// Ensure the ICU output matches Number.prototype.toFixed. +function formatToFixed(x) { + var mfd = format.resolvedOptions().maximumFractionDigits; + var s = x.toFixed(mfd); + + // To keep it simple we assume |s| is always in exponential form. + var m = s.match(/^(\d)\.(\d+)e\+(\d+)$/); + assertEq(m !== null, true); + s = m[1] + m[2].padEnd(m[3], "0"); + + // Group digits and append fractional part. + m = s.match(/\d{1,3}(?=(?:\d{3})*$)/g); + assertEq(m !== null, true); + return m.join(".") + ",0"; +} + +assertEq(formatToFixed(1123123123123123123123.1), "1.123.123.123.123.123.100.000,0"); +assertEq(formatToFixed(12123123123123123123123.1), "12.123.123.123.123.122.000.000,0"); +assertEq(formatToFixed(123123123123123123123123.1), "123.123.123.123.123.120.000.000,0"); + +reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/NumberFormat/bigint-int64.js b/js/src/tests/non262/Intl/NumberFormat/bigint-int64.js new file mode 100644 index 0000000000..7b670d0873 --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/bigint-int64.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Ensure the int64_t optimization when formatting a BigInt value works correctly by testing with +// various integers around the (u)int[32,64] limits. + +const limits = { + int32: { + min: -0x80000000n, + max: 0x7FFFFFFFn, + }, + uint32: { + min: 0n, + max: 0xFFFFFFFFn + }, + int64: { + min: -0x8000000000000000n, + max: 0x7FFFFFFFFFFFFFFFn, + }, + uint64: { + min: 0n, + max: 0xFFFFFFFFFFFFFFFFn + }, +}; + +const nf = new Intl.NumberFormat("en", {useGrouping: false}); + +const diff = 10n; + +for (const int of Object.values(limits)) { + for (let i = -diff; i <= diff; ++i) { + let n = int.min + i; + assertEq(nf.format(n), n.toString()); + + let m = int.max + i; + assertEq(nf.format(m), m.toString()); + } +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/browser.js b/js/src/tests/non262/Intl/NumberFormat/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Intl/NumberFormat/call.js b/js/src/tests/non262/Intl/NumberFormat/call.js new file mode 100644 index 0000000000..14ecf99eb5 --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/call.js @@ -0,0 +1,184 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +function IsIntlService(c) { + return typeof c === "function" && + c.hasOwnProperty("prototype") && + c.prototype.hasOwnProperty("resolvedOptions"); +} + +function IsObject(o) { + return Object(o) === o; +} + +function IsPrimitive(o) { + return Object(o) !== o; +} + +function thisValues() { + const intlConstructors = Object.getOwnPropertyNames(Intl).map(name => Intl[name]).filter(IsIntlService); + + return [ + // Primitive values. + ...[undefined, null, true, "abc", Symbol(), 123], + + // Object values. + ...[{}, [], /(?:)/, function(){}, new Proxy({}, {})], + + // Intl objects. + ...[].concat(...intlConstructors.map(ctor => { + let args = []; + if (ctor === Intl.DisplayNames) { + // Intl.DisplayNames can't be constructed without any arguments. + args = [undefined, {type: "language"}]; + } + + return [ + // Instance of an Intl constructor. + new ctor(...args), + + // Instance of a subclassed Intl constructor. + new class extends ctor {}(...args), + + // Object inheriting from an Intl constructor prototype. + Object.create(ctor.prototype), + + // Intl object not inheriting from its default prototype. + Object.setPrototypeOf(new ctor(...args), Object.prototype), + ]; + })), + ]; +} + +const intlFallbackSymbol = Object.getOwnPropertySymbols(Intl.NumberFormat.call(Object.create(Intl.NumberFormat.prototype)))[0]; + +// Invoking [[Call]] for Intl.NumberFormat returns a new instance unless called +// with an instance inheriting from Intl.NumberFormat.prototype. +for (let thisValue of thisValues()) { + let obj = Intl.NumberFormat.call(thisValue); + + if (!Intl.NumberFormat.prototype.isPrototypeOf(thisValue)) { + assertEq(Object.is(obj, thisValue), false); + assertEq(obj instanceof Intl.NumberFormat, true); + if (IsObject(thisValue)) + assertEqArray(Object.getOwnPropertySymbols(thisValue), []); + } else { + assertEq(Object.is(obj, thisValue), true); + assertEq(obj instanceof Intl.NumberFormat, true); + assertEqArray(Object.getOwnPropertySymbols(thisValue), [intlFallbackSymbol]); + } +} + +// Intl.NumberFormat uses the legacy Intl constructor compromise semantics. +// - Test when InstanceofOperator(thisValue, %NumberFormat%) returns true. +for (let thisValue of thisValues().filter(IsObject)) { + let isPrototypeOf = Intl.NumberFormat.prototype.isPrototypeOf(thisValue); + let hasInstanceCalled = false; + Object.defineProperty(Intl.NumberFormat, Symbol.hasInstance, { + value() { + assertEq(hasInstanceCalled, false); + hasInstanceCalled = true; + return true; + }, configurable: true + }); + let obj = Intl.NumberFormat.call(thisValue); + delete Intl.NumberFormat[Symbol.hasInstance]; + + assertEq(Object.is(obj, thisValue), isPrototypeOf); + assertEq(hasInstanceCalled, false); + assertEqArray(Object.getOwnPropertySymbols(thisValue), isPrototypeOf ? [intlFallbackSymbol] : []); +} +// - Test when InstanceofOperator(thisValue, %NumberFormat%) returns false. +for (let thisValue of thisValues().filter(IsObject)) { + let isPrototypeOf = Intl.NumberFormat.prototype.isPrototypeOf(thisValue); + let hasInstanceCalled = false; + Object.defineProperty(Intl.NumberFormat, Symbol.hasInstance, { + value() { + assertEq(hasInstanceCalled, false); + hasInstanceCalled = true; + return false; + }, configurable: true + }); + let obj = Intl.NumberFormat.call(thisValue); + delete Intl.NumberFormat[Symbol.hasInstance]; + + assertEq(Object.is(obj, thisValue), isPrototypeOf); + assertEq(obj instanceof Intl.NumberFormat, true); + assertEq(hasInstanceCalled, false); + assertEqArray(Object.getOwnPropertySymbols(thisValue), isPrototypeOf ? [intlFallbackSymbol] : []); +} +// - Test with primitive values. +for (let thisValue of thisValues().filter(IsPrimitive)) { + // Ensure @@hasInstance is not called. + Object.defineProperty(Intl.NumberFormat, Symbol.hasInstance, { + value() { assertEq(true, false); }, configurable: true + }); + let obj = Intl.NumberFormat.call(thisValue); + delete Intl.NumberFormat[Symbol.hasInstance]; + + assertEq(Object.is(obj, thisValue), false); + assertEq(obj instanceof Intl.NumberFormat, true); +} + +// Throws an error when attempting to install [[FallbackSymbol]] twice. +{ + let thisValue = Object.create(Intl.NumberFormat.prototype); + assertEqArray(Object.getOwnPropertySymbols(thisValue), []); + + assertEq(Intl.NumberFormat.call(thisValue), thisValue); + assertEqArray(Object.getOwnPropertySymbols(thisValue), [intlFallbackSymbol]); + + assertThrowsInstanceOf(() => Intl.NumberFormat.call(thisValue), TypeError); + assertEqArray(Object.getOwnPropertySymbols(thisValue), [intlFallbackSymbol]); +} + +// Throws an error when the thisValue is non-extensible. +{ + let thisValue = Object.create(Intl.NumberFormat.prototype); + Object.preventExtensions(thisValue); + + assertThrowsInstanceOf(() => Intl.NumberFormat.call(thisValue), TypeError); + assertEqArray(Object.getOwnPropertySymbols(thisValue), []); +} + +// [[FallbackSymbol]] is installed as a frozen property holding an Intl.NumberFormat instance. +{ + let thisValue = Object.create(Intl.NumberFormat.prototype); + Intl.NumberFormat.call(thisValue); + + let desc = Object.getOwnPropertyDescriptor(thisValue, intlFallbackSymbol); + assertEq(desc !== undefined, true); + assertEq(desc.writable, false); + assertEq(desc.enumerable, false); + assertEq(desc.configurable, false); + assertEq(desc.value instanceof Intl.NumberFormat, true); +} + +// Ensure [[FallbackSymbol]] is installed last by changing the [[Prototype]] +// during initialization. +{ + let thisValue = {}; + let options = { + get useGrouping() { + Object.setPrototypeOf(thisValue, Intl.NumberFormat.prototype); + return false; + } + }; + let obj = Intl.NumberFormat.call(thisValue, undefined, options); + assertEq(Object.is(obj, thisValue), true); + assertEqArray(Object.getOwnPropertySymbols(thisValue), [intlFallbackSymbol]); +} +{ + let thisValue = Object.create(Intl.NumberFormat.prototype); + let options = { + get useGrouping() { + Object.setPrototypeOf(thisValue, Object.prototype); + return false; + } + }; + let obj = Intl.NumberFormat.call(thisValue, undefined, options); + assertEq(Object.is(obj, thisValue), false); + assertEqArray(Object.getOwnPropertySymbols(thisValue), []); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/construct-newtarget.js b/js/src/tests/non262/Intl/NumberFormat/construct-newtarget.js new file mode 100644 index 0000000000..0053b2737e --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/construct-newtarget.js @@ -0,0 +1,81 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +// Test subclassing %Intl.NumberFormat% works correctly. +class MyNumberFormat extends Intl.NumberFormat {} + +var obj = new MyNumberFormat(); +assertEq(obj instanceof MyNumberFormat, true); +assertEq(obj instanceof Intl.NumberFormat, true); +assertEq(Object.getPrototypeOf(obj), MyNumberFormat.prototype); + +obj = Reflect.construct(MyNumberFormat, []); +assertEq(obj instanceof MyNumberFormat, true); +assertEq(obj instanceof Intl.NumberFormat, true); +assertEq(Object.getPrototypeOf(obj), MyNumberFormat.prototype); + +obj = Reflect.construct(MyNumberFormat, [], MyNumberFormat); +assertEq(obj instanceof MyNumberFormat, true); +assertEq(obj instanceof Intl.NumberFormat, true); +assertEq(Object.getPrototypeOf(obj), MyNumberFormat.prototype); + +obj = Reflect.construct(MyNumberFormat, [], Intl.NumberFormat); +assertEq(obj instanceof MyNumberFormat, false); +assertEq(obj instanceof Intl.NumberFormat, true); +assertEq(Object.getPrototypeOf(obj), Intl.NumberFormat.prototype); + + +// Set a different constructor as NewTarget. +obj = Reflect.construct(MyNumberFormat, [], Array); +assertEq(obj instanceof MyNumberFormat, false); +assertEq(obj instanceof Intl.NumberFormat, false); +assertEq(obj instanceof Array, true); +assertEq(Object.getPrototypeOf(obj), Array.prototype); + +obj = Reflect.construct(Intl.NumberFormat, [], Array); +assertEq(obj instanceof Intl.NumberFormat, false); +assertEq(obj instanceof Array, true); +assertEq(Object.getPrototypeOf(obj), Array.prototype); + + +// The prototype defaults to %NumberFormatPrototype% if null. +function NewTargetNullPrototype() {} +NewTargetNullPrototype.prototype = null; + +obj = Reflect.construct(Intl.NumberFormat, [], NewTargetNullPrototype); +assertEq(obj instanceof Intl.NumberFormat, true); +assertEq(Object.getPrototypeOf(obj), Intl.NumberFormat.prototype); + +obj = Reflect.construct(MyNumberFormat, [], NewTargetNullPrototype); +assertEq(obj instanceof MyNumberFormat, false); +assertEq(obj instanceof Intl.NumberFormat, true); +assertEq(Object.getPrototypeOf(obj), Intl.NumberFormat.prototype); + + +// "prototype" property is retrieved exactly once. +var trapLog = [], getLog = []; +var ProxiedConstructor = new Proxy(Intl.NumberFormat, new Proxy({ + get(target, propertyKey, receiver) { + getLog.push(propertyKey); + return Reflect.get(target, propertyKey, receiver); + } +}, { + get(target, propertyKey, receiver) { + trapLog.push(propertyKey); + return Reflect.get(target, propertyKey, receiver); + } +})); + +obj = Reflect.construct(Intl.NumberFormat, [], ProxiedConstructor); +assertEqArray(trapLog, ["get"]); +assertEqArray(getLog, ["prototype"]); +assertEq(obj instanceof Intl.NumberFormat, true); +assertEq(Object.getPrototypeOf(obj), Intl.NumberFormat.prototype); + + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/NumberFormat/cross-compartment.js b/js/src/tests/non262/Intl/NumberFormat/cross-compartment.js new file mode 100644 index 0000000000..806f889d6f --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/cross-compartment.js @@ -0,0 +1,70 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +var otherGlobal = newGlobal(); + +var numberFormat = new Intl.NumberFormat(); +var ccwNumberFormat = new otherGlobal.Intl.NumberFormat(); + +// Test Intl.NumberFormat.prototype.format with a CCW object. +var Intl_NumberFormat_format_get = Object.getOwnPropertyDescriptor(Intl.NumberFormat.prototype, "format").get; + +assertEq(Intl_NumberFormat_format_get.call(ccwNumberFormat)(0), + Intl_NumberFormat_format_get.call(numberFormat)(0)); + +// Test Intl.NumberFormat.prototype.formatToParts with a CCW object. +var Intl_NumberFormat_formatToParts = Intl.NumberFormat.prototype.formatToParts; + +assertEq(deepEqual(Intl_NumberFormat_formatToParts.call(ccwNumberFormat, 0), + Intl_NumberFormat_formatToParts.call(numberFormat, 0)), + true); + +// Test Intl.NumberFormat.prototype.resolvedOptions with a CCW object. +var Intl_NumberFormat_resolvedOptions = Intl.NumberFormat.prototype.resolvedOptions; + +assertEq(deepEqual(Intl_NumberFormat_resolvedOptions.call(ccwNumberFormat), + Intl_NumberFormat_resolvedOptions.call(numberFormat)), + true); + +// Special case for Intl.NumberFormat: The Intl fallback symbol. + +function fallbackSymbol(global) { + var NF = global.Intl.NumberFormat; + return Object.getOwnPropertySymbols(NF.call(Object.create(NF.prototype)))[0]; +} + +const intlFallbackSymbol = fallbackSymbol(this); +const otherIntlFallbackSymbol = fallbackSymbol(otherGlobal); +assertEq(intlFallbackSymbol === otherIntlFallbackSymbol, false); + +// Test when the fallback symbol points to a CCW NumberFormat object. +var objWithFallbackCCWNumberFormat = { + __proto__: Intl.NumberFormat.prototype, + [intlFallbackSymbol]: ccwNumberFormat, +}; + +assertEq(Intl_NumberFormat_format_get.call(objWithFallbackCCWNumberFormat)(0), + Intl_NumberFormat_format_get.call(numberFormat)(0)); + +assertEq(deepEqual(Intl_NumberFormat_resolvedOptions.call(objWithFallbackCCWNumberFormat), + Intl_NumberFormat_resolvedOptions.call(numberFormat)), + true); + +// Ensure the fallback symbol(s) are not accessed for CCW NumberFormat objects. +var ccwNumberFormatWithPoisonedFallback = new otherGlobal.Intl.NumberFormat(); +Object.setPrototypeOf(ccwNumberFormatWithPoisonedFallback, Intl.NumberFormat.prototype); +Object.defineProperty(ccwNumberFormatWithPoisonedFallback, intlFallbackSymbol, { + get() { throw new Error(); } +}); +Object.defineProperty(ccwNumberFormatWithPoisonedFallback, otherIntlFallbackSymbol, { + get() { throw new Error(); } +}); + +assertEq(Intl_NumberFormat_format_get.call(ccwNumberFormatWithPoisonedFallback)(0), + Intl_NumberFormat_format_get.call(numberFormat)(0)); + +assertEq(deepEqual(Intl_NumberFormat_resolvedOptions.call(ccwNumberFormatWithPoisonedFallback), + Intl_NumberFormat_resolvedOptions.call(numberFormat)), + true); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/currency-narrow-symbol.js b/js/src/tests/non262/Intl/NumberFormat/currency-narrow-symbol.js new file mode 100644 index 0000000000..bf2b9adcd8 --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/currency-narrow-symbol.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const { + Integer, Decimal, Fraction, Currency, Literal, +} = NumberFormatParts; + +const testcases = [ + { + locale: "en-CA", + options: { + style: "currency", + currency: "USD", + currencyDisplay: "narrowSymbol", + }, + values: [ + {value: 123, string: "US$123.00", + parts: [Currency("US$"), Integer("123"), Decimal("."), Fraction("00")]}, + ], + }, + + // And for comparison "symbol" currency-display. + + { + locale: "en-CA", + options: { + style: "currency", + currency: "USD", + currencyDisplay: "symbol", + }, + values: [ + {value: 123, string: "US$123.00", + parts: [Currency("US$"), Integer("123"), Decimal("."), Fraction("00")]}, + ], + }, +]; + +runNumberFormattingTestcases(testcases); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/currency-sign-accounting.js b/js/src/tests/non262/Intl/NumberFormat/currency-sign-accounting.js new file mode 100644 index 0000000000..6f91d6edd4 --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/currency-sign-accounting.js @@ -0,0 +1,192 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const { + Nan, Inf, Integer, MinusSign, PlusSign, Decimal, Fraction, + Currency, Literal, +} = NumberFormatParts; + +const testcases = [ + // "auto": Show the sign on negative numbers only. + { + locale: "en", + options: { + style: "currency", + currency: "USD", + currencySign: "accounting", + signDisplay: "auto", + }, + values: [ + {value: +0, string: "$0.00", + parts: [Currency("$"), Integer("0"), Decimal("."), Fraction("00")]}, + {value: -0, string: "($0.00)", + parts: [Literal("("), Currency("$"), Integer("0"), Decimal("."), Fraction("00"), Literal(")")]}, + + {value: 1, string: "$1.00", + parts: [Currency("$"), Integer("1"), Decimal("."), Fraction("00")]}, + {value: -1, string: "($1.00)", + parts: [Literal("("), Currency("$"), Integer("1"), Decimal("."), Fraction("00"), Literal(")")]}, + + {value: Infinity, string: "$∞", parts: [Currency("$"), Inf("∞")]}, + {value: -Infinity, string: "($∞)", parts: [Literal("("), Currency("$"), Inf("∞"), Literal(")")]}, + + {value: NaN, string: "$NaN", parts: [Currency("$"), Nan("NaN")]}, + {value: -NaN, string: "$NaN", parts: [Currency("$"), Nan("NaN")]}, + ], + }, + + // "never": Show the sign on neither positive nor negative numbers. + { + locale: "en", + options: { + style: "currency", + currency: "USD", + currencySign: "accounting", + signDisplay: "never", + }, + values: [ + {value: +0, string: "$0.00", parts: [Currency("$"), Integer("0"), Decimal("."), Fraction("00")]}, + {value: -0, string: "$0.00", parts: [Currency("$"), Integer("0"), Decimal("."), Fraction("00")]}, + + {value: 1, string: "$1.00", parts: [Currency("$"), Integer("1"), Decimal("."), Fraction("00")]}, + {value: -1, string: "$1.00", parts: [Currency("$"), Integer("1"), Decimal("."), Fraction("00")]}, + + {value: Infinity, string: "$∞", parts: [Currency("$"), Inf("∞")]}, + {value: -Infinity, string: "$∞", parts: [Currency("$"), Inf("∞")]}, + + {value: NaN, string: "$NaN", parts: [Currency("$"), Nan("NaN")]}, + {value: -NaN, string: "$NaN", parts: [Currency("$"), Nan("NaN")]}, + ], + }, + + // "always": Show the sign on positive and negative numbers including zero. + { + locale: "en", + options: { + style: "currency", + currency: "USD", + currencySign: "accounting", + signDisplay: "always", + }, + values: [ + {value: +0, string: "+$0.00", + parts: [PlusSign("+"), Currency("$"), Integer("0"), Decimal("."), Fraction("00")]}, + {value: -0, string: "($0.00)", + parts: [Literal("("), Currency("$"), Integer("0"), Decimal("."), Fraction("00"), Literal(")")]}, + + {value: 1, string: "+$1.00", + parts: [PlusSign("+"), Currency("$"), Integer("1"), Decimal("."), Fraction("00")]}, + {value: -1, string: "($1.00)", + parts: [Literal("("), Currency("$"), Integer("1"), Decimal("."), Fraction("00"), Literal(")")]}, + + {value: Infinity, string: "+$∞", parts: [PlusSign("+"), Currency("$"), Inf("∞")]}, + {value: -Infinity, string: "($∞)", parts: [Literal("("), Currency("$"), Inf("∞"), Literal(")")]}, + + {value: NaN, string: "+$NaN", parts: [PlusSign("+"), Currency("$"), Nan("NaN")]}, + {value: -NaN, string: "+$NaN", parts: [PlusSign("+"), Currency("$"), Nan("NaN")]}, + ], + }, + + // "exceptZero": Show the sign on positive and negative numbers but not zero. + { + locale: "en", + options: { + style: "currency", + currency: "USD", + currencySign: "accounting", + signDisplay: "exceptZero", + }, + values: [ + {value: +0, string: "$0.00", + parts: [Currency("$"), Integer("0"), Decimal("."), Fraction("00")]}, + {value: -0, string: "$0.00", + parts: [Currency("$"), Integer("0"), Decimal("."), Fraction("00")]}, + + {value: 1, string: "+$1.00", + parts: [PlusSign("+"), Currency("$"), Integer("1"), Decimal("."), Fraction("00")]}, + {value: -1, string: "($1.00)", + parts: [Literal("("), Currency("$"), Integer("1"), Decimal("."), Fraction("00"), Literal(")")]}, + + {value: Infinity, string: "+$∞", parts: [PlusSign("+"), Currency("$"), Inf("∞")]}, + {value: -Infinity, string: "($∞)", parts: [Literal("("), Currency("$"), Inf("∞"), Literal(")")]}, + + {value: NaN, string: "$NaN", parts: [Currency("$"), Nan("NaN")]}, + {value: -NaN, string: "$NaN", parts: [Currency("$"), Nan("NaN")]}, + ], + }, + + // Tests with suppressed fractional digits. + + // "auto": Show the sign on negative numbers only. + { + locale: "en", + options: { + style: "currency", + currency: "USD", + currencySign: "accounting", + signDisplay: "auto", + minimumFractionDigits: 0, + maximumFractionDigits: 0, + }, + values: [ + {value: +0.1, string: "$0", parts: [Currency("$"), Integer("0")]}, + {value: -0.1, string: "($0)", parts: [Literal("("), Currency("$"), Integer("0"), Literal(")")]}, + ], + }, + + // "never": Show the sign on neither positive nor negative numbers. + { + locale: "en", + options: { + style: "currency", + currency: "USD", + currencySign: "accounting", + signDisplay: "never", + minimumFractionDigits: 0, + maximumFractionDigits: 0, + }, + values: [ + {value: +0.1, string: "$0", parts: [Currency("$"), Integer("0")]}, + {value: -0.1, string: "$0", parts: [Currency("$"), Integer("0")]}, + ], + }, + + // "always": Show the sign on positive and negative numbers including zero. + { + locale: "en", + options: { + style: "currency", + currency: "USD", + currencySign: "accounting", + signDisplay: "always", + minimumFractionDigits: 0, + maximumFractionDigits: 0, + }, + values: [ + {value: +0.1, string: "+$0", parts: [PlusSign("+"), Currency("$"), Integer("0")]}, + {value: -0.1, string: "($0)", parts: [Literal("("), Currency("$"), Integer("0"), Literal(")")]}, + ], + }, + + // "exceptZero": Show the sign on positive and negative numbers but not zero. + { + locale: "en", + options: { + style: "currency", + currency: "USD", + currencySign: "accounting", + signDisplay: "exceptZero", + minimumFractionDigits: 0, + maximumFractionDigits: 0, + }, + + values: [ + {value: +0.1, string: "$0", parts: [Currency("$"), Integer("0")]}, + {value: -0.1, string: "$0", parts: [Currency("$"), Integer("0")]}, + ], + } +]; + +runNumberFormattingTestcases(testcases); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/duplicate-singleton-variant.js b/js/src/tests/non262/Intl/NumberFormat/duplicate-singleton-variant.js new file mode 100644 index 0000000000..42bf78c3fe --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/duplicate-singleton-variant.js @@ -0,0 +1,49 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Check for duplicate variants and singletons case-insensitively, but don't +// check in privateuse components. + +function checkInvalidLocale(locale) +{ + try + { + new Intl.NumberFormat(locale); + throw new Error("didn't throw"); + } + catch (e) + { + assertEq(e instanceof RangeError, true, + "expected RangeError for locale '" + locale + "', got " + e); + } +} + +var badLocales = + [ + "en-u-foo-U-foo", + "en-tester-Tester", + "en-tesTER-TESter", + "de-DE-u-kn-true-U-kn-true", + "ar-u-foo-q-bar-u-baz", + "ar-z-moo-u-foo-q-bar-z-eit-u-baz", + ]; + +for (var locale of badLocales) + checkInvalidLocale(locale); + +// Fully-privateuse locales are rejected. +for (var locale of badLocales) + assertThrowsInstanceOf(() => new Intl.NumberFormat("x-" + locale), RangeError); + +// Locales with trailing privateuse also okay. +for (var locale of badLocales) +{ + new Intl.NumberFormat("en-x-" + locale).format(5); + new Intl.NumberFormat("en-u-foo-x-u-" + locale).format(5); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/format-as-code-or-name.js b/js/src/tests/non262/Intl/NumberFormat/format-as-code-or-name.js new file mode 100644 index 0000000000..ba257ecd71 --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/format-as-code-or-name.js @@ -0,0 +1,75 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 1093421; +var summary = + "new Intl.NumberFormat(..., { style: 'currency', currency: '...', " + + "currencyDisplay: 'name' or 'code' }) should have behavior other than " + + "throwing"; + +print(BUGNUMBER + ": " + summary); + +//----------------------------------------------------------------------------- + +// Test that currencyDisplay: "code" behaves correctly and doesn't throw. + +var usdCodeOptions = + { + style: "currency", + currency: "USD", + currencyDisplay: "code", + minimumFractionDigits: 0, + maximumFractionDigits: 0, + }; +var usDollarsCode = new Intl.NumberFormat("en-US", usdCodeOptions); +assertEq(/USD/.test(usDollarsCode.format(25)), true); + +// ISO 4217 currency codes are formed from an ISO 3166-1 alpha-2 country code +// followed by a third letter. ISO 3166 guarantees that no country code +// starting with "X" will ever be assigned. Stepping carefully around a few +// 4217-designated special "currencies", XQQ will never have a representation. +// Thus, yes: this really is specified to work, as unrecognized or unsupported +// codes pass into the string unmodified. +var xqqCodeOptions = + { + style: "currency", + currency: "XQQ", + currencyDisplay: "code", + minimumFractionDigits: 0, + maximumFractionDigits: 0, + }; +var xqqMoneyCode = new Intl.NumberFormat("en-US", xqqCodeOptions); +assertEq(/XQQ/.test(xqqMoneyCode.format(25)), true); + +// Test that currencyDisplay: "name" behaves without throwing. (Unlike the two +// above tests, the results here aren't guaranteed as the name is +// implementation-defined.) +var usdNameOptions = + { + style: "currency", + currency: "USD", + currencyDisplay: "name", + minimumFractionDigits: 0, + maximumFractionDigits: 0, + }; +var usDollarsName = new Intl.NumberFormat("en-US", usdNameOptions); +assertEq(usDollarsName.format(25), "25 US dollars"); + +// But if the implementation doesn't recognize the currency, the provided code +// is used in place of a proper name, unmolested. +var xqqNameOptions = + { + style: "currency", + currency: "XQQ", + currencyDisplay: "name", + minimumFractionDigits: 0, + maximumFractionDigits: 0, + }; +var xqqMoneyName = new Intl.NumberFormat("en-US", xqqNameOptions); +assertEq(/XQQ/.test(xqqMoneyName.format(25)), true); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/format-string.js b/js/src/tests/non262/Intl/NumberFormat/format-string.js new file mode 100644 index 0000000000..ec83b5147a --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/format-string.js @@ -0,0 +1,149 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +function groupByThree(s) { + return String(s).split("").reduceRight((acc, x) => x + (acc.match(/^\d{3}/) ? "," : "") + acc, ""); +} + +const tests = [ + {value: "", expected: "0"}, + {value: "0", expected: "0"}, + {value: "+0", expected: "0"}, + {value: "-0", expected: "-0"}, + + {value: "Infinity", expected: "∞"}, + {value: "+Infinity", expected: "∞"}, + {value: "-Infinity", expected: "-∞"}, + + {value: "NaN", expected: "NaN"}, + {value: "invalid", expected: "NaN"}, + + // Integer 1 with and without fractional/exponent part. + {value: "1", expected: "1"}, + {value: "1.", expected: "1"}, + {value: "1.0", expected: "1"}, + {value: "1.00", expected: "1"}, + {value: "1e0", expected: "1"}, + {value: "1e+0", expected: "1"}, + {value: "1e-0", expected: "1"}, + + // Leading zeros. + {value: "01", expected: "1"}, + {value: "01.", expected: "1"}, + {value: "01.0", expected: "1"}, + {value: "01.00", expected: "1"}, + {value: "01e0", expected: "1"}, + {value: "01e+0", expected: "1"}, + {value: "01e-0", expected: "1"}, + + // Large values. + {value: "1e300", expected: "1" + ",000".repeat(100)}, + {value: "1e308", expected: "100" + ",000".repeat(102)}, + {value: "1e309", expected: "∞"}, + {value: "1e3000", expected: "∞"}, + {value: "1e+9999999", expected: "∞"}, + {value: "1e+99999999", expected: "∞"}, + {value: ".1e+9999999", expected: "∞"}, + {value: ".1e+99999999", expected: "∞"}, + {value: ".1e+999999999", expected: "∞"}, + {value: ".1e+9999999999", expected: "∞"}, + {value: "9007199254740991", expected: "9,007,199,254,740,991"}, + {value: "9007199254740992", expected: "9,007,199,254,740,992"}, + {value: "9007199254740993", expected: "9,007,199,254,740,993"}, + + {value: "-1e300", expected: "-1" + ",000".repeat(100)}, + {value: "-1e308", expected: "-100" + ",000".repeat(102)}, + {value: "-1e309", expected: "-∞"}, + {value: "-1e3000", expected: "-∞"}, + {value: "-1e+9999999", expected: "-∞"}, + {value: "-1e+99999999", expected: "-∞"}, + {value: "-.1e+9999999", expected: "-∞"}, + {value: "-.1e+99999999", expected: "-∞"}, + {value: "-.1e+999999999", expected: "-∞"}, + {value: "-.1e+9999999999", expected: "-∞"}, + {value: "-9007199254740991", expected: "-9,007,199,254,740,991"}, + {value: "-9007199254740992", expected: "-9,007,199,254,740,992"}, + {value: "-9007199254740993", expected: "-9,007,199,254,740,993"}, + + // Small values. + {value: "0.10000000000000000001", expected: "0.10000000000000000001"}, + {value: "0.00000000000000000001", expected: "0.00000000000000000001"}, + {value: "1e-20", expected: "0.00000000000000000001"}, + {value: "1e-30", expected: "0"}, + {value: ".1e-9999999", expected: "0"}, + {value: ".1e-99999999", expected: "0"}, + {value: ".1e-999999999", expected: "0"}, + {value: ".1e-9999999999", expected: "0"}, + + {value: "-0.10000000000000000001", expected: "-0.10000000000000000001"}, + {value: "-0.00000000000000000001", expected: "-0.00000000000000000001"}, + {value: "-1e-20", expected: "-0.00000000000000000001"}, + {value: "-1e-30", expected: "-0"}, + {value: "-.1e-9999999", expected: "-0"}, + {value: "-.1e-99999999", expected: "-0"}, + {value: "-.1e-999999999", expected: "-0"}, + {value: "-.1e-9999999999", expected: "-0"}, + + // Non-standard exponent notation. + {value: ".001e-2", expected: "0.00001"}, + {value: "123.001e-2", expected: "1.23001"}, + {value: "1000e-2", expected: "10"}, + {value: "1000e+2", expected: "100,000"}, + {value: "1000e-0", expected: "1,000"}, + + // Non-decimal strings. + {value: "0b101", expected: "5"}, + {value: "0o377", expected: "255"}, + {value: "0xdeadBEEF", expected: "3,735,928,559"}, + {value: "0B0011", expected: "3"}, + {value: "0O0777", expected: "511"}, + {value: "0X0ABC", expected: "2,748"}, + {value: "0b" + "1".repeat(1000), expected: groupByThree((2n ** 1000n) - 1n)}, + {value: "0o1" + "7".repeat(333), expected: groupByThree((2n ** 1000n) - 1n)}, + {value: "0x" + "f".repeat(250), expected: groupByThree((2n ** 1000n) - 1n)}, + + {value: "0b" + "1".repeat(1023), expected: groupByThree(0b10n ** 1023n - 1n)}, + {value: "0b" + "1".repeat(1024), expected: "∞"}, + {value: "0o" + "7".repeat(341), expected: groupByThree(0o10n ** 341n - 1n)}, + {value: "0o" + "7".repeat(342), expected: "∞"}, + {value: "0x" + "f".repeat(255), expected: groupByThree(0x10n ** 255n - 1n)}, + {value: "0x" + "f".repeat(256), expected: "∞"}, + + // Non-decimal strings don't accept a sign. + {value: "+0xbad", expected: "NaN"}, + {value: "-0xbad", expected: "NaN"}, +]; + +// https://tc39.es/ecma262/#prod-StrWhiteSpaceChar +const strWhiteSpaceChar = [ + "", + + // https://tc39.es/ecma262/#sec-white-space + "\t", "\v", "\f", " ", "\u00A0", "\uFEFF", + "\u1680", "\u2000", "\u2001", "\u2002", "\u2003", "\u2004", "\u2005", "\u2006", + "\u2007", "\u2008", "\u2009", "\u200A", "\u202F", "\u205F", "\u3000", + + // https://tc39.es/ecma262/#sec-line-terminators + "\n", "\r", "\u2028", "\u2029", +]; + +let nf = new Intl.NumberFormat("en", {maximumFractionDigits: 20}); +for (let {value, expected} of tests) { + for (let ws of strWhiteSpaceChar) { + assertEq(nf.format(ws + value), expected); + assertEq(nf.format(value + ws), expected); + assertEq(nf.format(ws + value + ws), expected); + } +} + +// Combine extreme values with other rounding modes. +{ + let nf = new Intl.NumberFormat("en", { + minimumFractionDigits: 20, + roundingMode: "ceil", + roundingIncrement: 5000, + }); + assertEq(nf.format(".1e-999999998"), "0.00000000000000000000"); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/format.js b/js/src/tests/non262/Intl/NumberFormat/format.js new file mode 100644 index 0000000000..db35251b20 --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/format.js @@ -0,0 +1,55 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Tests the format function with a diverse set of locales and options. + +var format; + +// Locale en-US; default options. +format = new Intl.NumberFormat("en-us"); +assertEq(format.format(0), "0"); +assertEq(format.format(-1), "-1"); +assertEq(format.format(123456789.123456789), "123,456,789.123"); + +// Locale en-US; currency USD. +// The US dollar uses two fractional digits, and negative values are commonly +// parenthesized. +format = new Intl.NumberFormat("en-us", {style: "currency", currency: "USD"}); +assertEq(format.format(0), "$0.00"); +assertEq(format.format(-1), "-$1.00"); +assertEq(format.format(123456789.123456789), "$123,456,789.12"); + +// Locale ja-JP; currency JPY. +// The Japanese yen has no subunit in real life. +format = new Intl.NumberFormat("ja-jp", {style: "currency", currency: "JPY"}); +assertEq(format.format(0), "¥0"); +assertEq(format.format(-1), "-¥1"); +assertEq(format.format(123456789.123456789), "¥123,456,789"); + +// Locale ar-JO; currency JOD. +// The Jordanian Dinar divides into 1000 fils. Jordan uses (real) Arabic digits. +format = new Intl.NumberFormat("ar-jo", {style: "currency", currency: "JOD"}); +assertEq(format.format(0), "\u{200F}٠٫٠٠٠ د.أ.\u{200F}"); +assertEq(format.format(-1), "\u{061C}-\u{200F}١٫٠٠٠ د.أ.\u{200F}"); +assertEq(format.format(123456789.123456789), "\u{200F}١٢٣٬٤٥٦٬٧٨٩٫١٢٣ د.أ.\u{200F}"); + +// Locale th-TH; Thai digits, percent, two significant digits. +format = new Intl.NumberFormat("th-th-u-nu-thai", + {style: "percent", + minimumSignificantDigits: 2, + maximumSignificantDigits: 2}); +assertEq(format.format(0), "๐.๐%"); +assertEq(format.format(-0.01), "-๑.๐%"); +assertEq(format.format(1.10), "๑๑๐%"); + + +// Test the .name property of the "format" getter. +var desc = Object.getOwnPropertyDescriptor(Intl.NumberFormat.prototype, "format"); +assertEq(desc !== undefined, true); +assertEq(typeof desc.get, "function"); +assertEq(desc.get.name, "get format"); + + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Intl/NumberFormat/formatRange-BigInt.js b/js/src/tests/non262/Intl/NumberFormat/formatRange-BigInt.js new file mode 100644 index 0000000000..f856073b71 --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/formatRange-BigInt.js @@ -0,0 +1,150 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Int64-BigInts which can be exactly represented as doubles receive a fast-path. + +const tests = { + "en": { + options: {}, + ranges: [ + // BigInt around Number.MIN_SAFE_INTEGER. + { + start: -0x20000000000001n, + end: -0x20000000000000n, + result: "-9,007,199,254,740,993 – -9,007,199,254,740,992", + }, + { + start: -0x20000000000000n, + end: -0x20000000000000n, + result: "~-9,007,199,254,740,992", + }, + { + start: -0x20000000000000n, + end: -0x1fffffffffffffn, + result: "-9,007,199,254,740,992 – -9,007,199,254,740,991", + }, + { + start: -0x1fffffffffffffn, + end: -0x1fffffffffffffn, + result: "~-9,007,199,254,740,991", + }, + { + start: -0x1fffffffffffffn, + end: -0x1ffffffffffffen, + result: "-9,007,199,254,740,991 – -9,007,199,254,740,990", + }, + { + start: -0x1ffffffffffffen, + end: -0x1ffffffffffffen, + result: "~-9,007,199,254,740,990", + }, + + // BigInt around Number.MAX_SAFE_INTEGER. + { + start: 0x1ffffffffffffen, + end: 0x1ffffffffffffen, + result: "~9,007,199,254,740,990", + }, + { + start: 0x1ffffffffffffen, + end: 0x1fffffffffffffn, + result: "9,007,199,254,740,990–9,007,199,254,740,991", + }, + { + start: 0x1fffffffffffffn, + end: 0x1fffffffffffffn, + result: "~9,007,199,254,740,991", + }, + { + start: 0x1fffffffffffffn, + end: 0x20000000000000n, + result: "9,007,199,254,740,991–9,007,199,254,740,992", + }, + { + start: 0x20000000000000n, + end: 0x20000000000000n, + result: "~9,007,199,254,740,992", + }, + { + start: 0x20000000000000n, + end: 0x20000000000001n, + result: "9,007,199,254,740,992–9,007,199,254,740,993", + }, + + // BigInt around INT64_MIN. + { + start: -0x8000000000000002n, + end: -0x8000000000000001n, + result: "-9,223,372,036,854,775,810 – -9,223,372,036,854,775,809", + }, + { + start: -0x8000000000000001n, + end: -0x8000000000000001n, + result: "~-9,223,372,036,854,775,809", + }, + { + start: -0x8000000000000001n, + end: -0x8000000000000000n, + result: "-9,223,372,036,854,775,809 – -9,223,372,036,854,775,808", + }, + { + start: -0x8000000000000000n, + end: -0x8000000000000000n, + result: "~-9,223,372,036,854,775,808", + }, + { + start: -0x8000000000000000n, + end: -0x7fffffffffffffffn, + result: "-9,223,372,036,854,775,808 – -9,223,372,036,854,775,807", + }, + { + start: -0x7fffffffffffffffn, + end: -0x7fffffffffffffffn, + result: "~-9,223,372,036,854,775,807", + }, + + // BigInt around INT64_MAX. + { + start: 0x7ffffffffffffffen, + end: 0x7ffffffffffffffen, + result: "~9,223,372,036,854,775,806", + }, + { + start: 0x7ffffffffffffffen, + end: 0x7fffffffffffffffn, + result: "9,223,372,036,854,775,806–9,223,372,036,854,775,807", + }, + { + start: 0x7fffffffffffffffn, + end: 0x7fffffffffffffffn, + result: "~9,223,372,036,854,775,807", + }, + { + start: 0x7fffffffffffffffn, + end: 0x8000000000000000n, + result: "9,223,372,036,854,775,807–9,223,372,036,854,775,808", + }, + { + start: 0x8000000000000000n, + end: 0x8000000000000000n, + result: "~9,223,372,036,854,775,808", + }, + { + start: 0x8000000000000000n, + end: 0x8000000000000001n, + result: "9,223,372,036,854,775,808–9,223,372,036,854,775,809", + }, + ], + }, +}; + +for (let [locale, {options, ranges}] of Object.entries(tests)) { + let nf = new Intl.NumberFormat(locale, options); + for (let {start, end, result} of ranges) { + assertEq(nf.formatRange(start, end), result, `${start}-${end}`); + assertEq(nf.formatRangeToParts(start, end).reduce((acc, part) => acc + part.value, ""), + result, `${start}-${end}`); + } +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/formatRange.js b/js/src/tests/non262/Intl/NumberFormat/formatRange.js new file mode 100644 index 0000000000..733d7e71a5 --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/formatRange.js @@ -0,0 +1,296 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// String representation for Number.MAX_VALUE. +const en_Number_MAX_VALUE = "179,769,313,486,231,570" + ",000".repeat(97); +const de_Number_MAX_VALUE = en_Number_MAX_VALUE.replaceAll(",", "."); +const fr_Number_MAX_VALUE = en_Number_MAX_VALUE.replaceAll(",", " "); + +const tests = { + "en": { + options: {}, + ranges: [ + // Values around zero. + {start: 0, end: 0, result: "~0"}, + {start: 0, end: -0, result: "0–-0"}, + {start: -0, end: 0, result: "-0 – 0"}, + {start: -0, end: 0.1e-3, result: "-0 – 0"}, + {start: -0, end: "0.1e-3", result: "-0 – 0"}, + {start: "-0", end: 0.1e-3, result: "-0 – 0"}, + {start: -0, end: -0, result: "~-0"}, + {start: -0, end: -0.1, result: "-0 – -0.1"}, + + // Values starting at negative infinity. + {start: -Infinity, end: -Infinity, result: "~-∞"}, + {start: -Infinity, end: -0, result: "-∞ – -0"}, + {start: -Infinity, end: +0, result: "-∞ – 0"}, + {start: -Infinity, end: +Infinity, result: "-∞ – ∞"}, + + // Values ending at negative infinity. + {start: -Number.MAX_VALUE, end: -Infinity, result: "-" + en_Number_MAX_VALUE + " – -∞"}, + {start: -0, end: -Infinity, result: "-0 – -∞"}, + {start: 0, end: -Infinity, result: "0–-∞"}, + {start: Number.MAX_VALUE, end: -Infinity, result: en_Number_MAX_VALUE + "–-∞"}, + + // Values starting at positive infinity. + {start: Infinity, end: Number.MAX_VALUE, result: "∞–" + en_Number_MAX_VALUE}, + {start: Infinity, end: 0, result: "∞–0"}, + {start: Infinity, end: -0, result: "∞–-0"}, + {start: Infinity, end: -Number.MAX_VALUE, result: "∞–-" + en_Number_MAX_VALUE}, + {start: Infinity, end: -Infinity, result: "∞–-∞"}, + + // Values ending at positive infinity. + {start: Infinity, end: Infinity, result: "~∞"}, + + // Non-special cases. + {start: 1, end: 100, result: "1–100"}, + {start: -100, end: 100, result: "-100 – 100"}, + {start: -1000, end: -100, result: "-1,000 – -100"}, + {start: Math.PI, end: 123_456.789, result: "3.142–123,456.789"}, + {start: -Math.PI, end: Math.E, result: "-3.142 – 2.718"}, + { + start: Number.MAX_SAFE_INTEGER, + end: 9007199254740993, + result: "9,007,199,254,740,991–9,007,199,254,740,992", + }, + { + start: Number.MAX_SAFE_INTEGER, + end: "9007199254740993", + result: "9,007,199,254,740,991–9,007,199,254,740,993", + }, + + // Start value is larger than end value. + {start: -0, end: -0.1, result: "-0 – -0.1"}, + {start: -0, end: -Number.MAX_VALUE, result: "-0 – -" + en_Number_MAX_VALUE}, + {start: 1, end: 0, result: "1–0"}, + {start: 0, end: -1, result: "0–-1"}, + {start: 1, end: -1, result: "1–-1"}, + {start: -1, end: -2, result: "-1 – -2"}, + {start: "10e2", end: "1e-3", result: "1,000–0.001"}, + {start: "0x100", end: "1e1", result: "256–10"}, + {start: ".1e-999999", end: ".01e-999999", result: "~0"}, + {start: ".1e99999", end: "0", result: "∞–0"}, + // Number.MAX_VALUE is 1.7976931348623157e+308. + { + start: "1.7976931348623158e+308", + end: Number.MAX_VALUE, + result: "179,769,313,486,231,580" + ",000".repeat(97) + "–" + en_Number_MAX_VALUE, + }, + // Number.MIN_VALUE is 5e-324. + {start: "6e-324", end: Number.MIN_VALUE, result: "~0"}, + ], + }, + "de": { + options: {style: "currency", currency: "EUR"}, + ranges: [ + // Values around zero. + {start: 0, end: 0, result: "≈0,00 €"}, + {start: 0, end: -0, result: "0,00 € – -0,00 €"}, + {start: -0, end: 0, result: "-0,00 € – 0,00 €"}, + {start: -0, end: 0.1e-3, result: "-0,00 € – 0,00 €"}, + {start: -0, end: "0.1e-3", result: "-0,00 € – 0,00 €"}, + {start: "-0", end: 0.1e-3, result: "-0,00 € – 0,00 €"}, + {start: -0, end: -0, result: "≈-0,00 €"}, + {start: -0, end: -0.1, result: "-0,00–0,10 €"}, + + // Values starting at negative infinity. + {start: -Infinity, end: -Infinity, result: "≈-∞ €"}, + {start: -Infinity, end: -0, result: "-∞–0,00 €"}, + {start: -Infinity, end: +0, result: "-∞ € – 0,00 €"}, + {start: -Infinity, end: +Infinity, result: "-∞ € – ∞ €"}, + + // Values ending at negative infinity. + {start: -Number.MAX_VALUE, end: -Infinity, result: "-" + de_Number_MAX_VALUE + ",00–∞ €"}, + {start: -0, end: -Infinity, result: "-0,00–∞ €"}, + {start: 0, end: -Infinity, result: "0,00 € – -∞ €"}, + {start: Number.MAX_VALUE, end: -Infinity, result: de_Number_MAX_VALUE + ",00 € – -∞ €"}, + + // Values starting at positive infinity. + {start: Infinity, end: Number.MAX_VALUE, result: "∞–" + de_Number_MAX_VALUE + ",00 €"}, + {start: Infinity, end: 0, result: "∞–0,00 €"}, + {start: Infinity, end: -0, result: "∞ € – -0,00 €"}, + {start: Infinity, end: -Number.MAX_VALUE, result: "∞ € – -" + de_Number_MAX_VALUE + ",00 €"}, + {start: Infinity, end: -Infinity, result: "∞ € – -∞ €"}, + + // Values ending at positive infinity. + {start: Infinity, end: Infinity, result: "≈∞ €"}, + + // Non-special cases. + {start: 1, end: 100, result: "1,00–100,00 €"}, + {start: -100, end: 100, result: "-100,00 € – 100,00 €"}, + {start: -1000, end: -100, result: "-1.000,00–100,00 €"}, + {start: Math.PI, end: 123_456.789, result: "3,14–123.456,79 €"}, + {start: -Math.PI, end: Math.E, result: "-3,14 € – 2,72 €"}, + { + start: Number.MAX_SAFE_INTEGER, + end: 9007199254740993, + result: "9.007.199.254.740.991,00–9.007.199.254.740.992,00 €", + }, + { + start: Number.MAX_SAFE_INTEGER, + end: "9007199254740993", + result: "9.007.199.254.740.991,00–9.007.199.254.740.993,00 €", + }, + + // Start value is larger than end value. + {start: -0, end: -0.1, result: "-0,00–0,10 €"}, + {start: -0, end: -Number.MAX_VALUE, result: "-0,00–" + de_Number_MAX_VALUE + ",00 €"}, + {start: 1, end: 0, result: "1,00–0,00 €"}, + {start: 0, end: -1, result: "0,00 € – -1,00 €"}, + {start: 1, end: -1, result: "1,00 € – -1,00 €"}, + {start: -1, end: -2, result: "-1,00–2,00 €"}, + {start: "10e2", end: "1e-3", result: "1.000,00–0,00 €"}, + {start: "0x100", end: "1e1", result: "256,00–10,00 €"}, + {start: ".1e-999999", end: ".01e-999999", result: "≈0,00 €"}, + {start: ".1e99999", end: "0", result: "∞–0,00 €"}, + // Number.MAX_VALUE is 1.7976931348623157e+308. + { + start: "1.7976931348623158e+308", + end: Number.MAX_VALUE, + result: "179.769.313.486.231.580" + ".000".repeat(97) + ",00–" + de_Number_MAX_VALUE + ",00 €", + }, + // Number.MIN_VALUE is 5e-324. + {start: "6e-324", end: Number.MIN_VALUE, result: "≈0,00 €"}, + ], + }, + "fr": { + options: {style: "unit", unit: "meter"}, + ranges: [ + // Values around zero. + {start: 0, end: 0, result: "≃0 m"}, + {start: -0, end: 0, result: "-0 – 0 m"}, + {start: -0, end: 0, result: "-0 – 0 m"}, + {start: -0, end: 0.1e-3, result: "-0 – 0 m"}, + {start: -0, end: "0.1e-3", result: "-0 – 0 m"}, + {start: "-0", end: 0.1e-3, result: "-0 – 0 m"}, + {start: -0, end: -0, result: "≃-0 m"}, + {start: -0, end: -0.1, result: "-0 – -0,1 m"}, + + // Values starting at negative infinity. + {start: -Infinity, end: -Infinity, result: "≃-∞ m"}, + {start: -Infinity, end: -0, result: "-∞ – -0 m"}, + {start: -Infinity, end: +0, result: "-∞ – 0 m"}, + {start: -Infinity, end: +Infinity, result: "-∞ – ∞ m"}, + + // Values ending at negative infinity. + {start: -Number.MAX_VALUE, end: -Infinity, result: "-" + fr_Number_MAX_VALUE + " – -∞ m"}, + {start: -0, end: -Infinity, result: "-0 – -∞ m"}, + {start: 0, end: -Infinity, result: "0–-∞ m"}, + {start: Number.MAX_VALUE, end: -Infinity, result: fr_Number_MAX_VALUE + "–-∞ m"}, + + // Values starting at positive infinity. + {start: Infinity, end: Number.MAX_VALUE, result: "∞–" + fr_Number_MAX_VALUE + " m"}, + {start: Infinity, end: 0, result: "∞–0 m"}, + {start: Infinity, end: -0, result: "∞–-0 m"}, + {start: Infinity, end: -Number.MAX_VALUE, result: "∞–-" + fr_Number_MAX_VALUE + " m"}, + {start: Infinity, end: -Infinity, result: "∞–-∞ m"}, + + // Values ending at positive infinity. + {start: Infinity, end: Infinity, result: "≃∞ m"}, + + // Non-special cases. + {start: 1, end: 100, result: "1–100 m"}, + {start: -100, end: 100, result: "-100 – 100 m"}, + {start: -1000, end: -100, result: "-1 000 – -100 m"}, + {start: Math.PI, end: 123_456.789, result: "3,142–123 456,789 m"}, + {start: -Math.PI, end: Math.E, result: "-3,142 – 2,718 m"}, + { + start: Number.MAX_SAFE_INTEGER, + end: 9007199254740993, + result: "9 007 199 254 740 991–9 007 199 254 740 992 m", + }, + { + start: Number.MAX_SAFE_INTEGER, + end: "9007199254740993", + result: "9 007 199 254 740 991–9 007 199 254 740 993 m", + }, + + // Start value is larger than end value. + {start: -0, end: -0.1, result: "-0 – -0,1 m"}, + {start: -0, end: -Number.MAX_VALUE, result: "-0 – -" + fr_Number_MAX_VALUE + " m"}, + {start: 1, end: 0, result: "1–0 m"}, + {start: 0, end: -1, result: "0–-1 m"}, + {start: 1, end: -1, result: "1–-1 m"}, + {start: -1, end: -2, result: "-1 – -2 m"}, + {start: "10e2", end: "1e-3", result: "1 000–0,001 m"}, + {start: "0x100", end: "1e1", result: "256–10 m"}, + {start: ".1e-999999", end: ".01e-999999", result: "≃0 m"}, + {start: ".1e99999", end: "0", result: "∞–0 m"}, + // Number.MAX_VALUE is 1.7976931348623157e+308. + { + start: "1.7976931348623158e+308", + end: Number.MAX_VALUE, + result: "179 769 313 486 231 580" + " 000".repeat(97) + "–" + fr_Number_MAX_VALUE + " m", + }, + // Number.MIN_VALUE is 5e-324. + {start: "6e-324", end: Number.MIN_VALUE, result: "≃0 m"}, + ], + }, + // Non-ASCII digits. + "ar": { + options: {}, + ranges: [ + {start: -2, end: -1, result: "؜-٢–١"}, + {start: -1, end: -1, result: "~؜-١"}, + {start: -1, end: 0, result: "؜-١ – ٠"}, + {start: 0, end: 0, result: "~٠"}, + {start: 0, end: 1, result: "٠–١"}, + {start: 1, end: 1, result: "~١"}, + {start: 1, end: 2, result: "١–٢"}, + ], + }, + "th-u-nu-thai": { + options: {}, + ranges: [ + {start: -2, end: -1, result: "-๒ - -๑"}, + {start: -1, end: -1, result: "~-๑"}, + {start: -1, end: 0, result: "-๑ - ๐"}, + {start: 0, end: 0, result: "~๐"}, + {start: 0, end: 1, result: "๐-๑"}, + {start: 1, end: 1, result: "~๑"}, + {start: 1, end: 2, result: "๑-๒"}, + ], + }, + // Approximation sign may consist of multiple characters. + "no": { + options: {}, + ranges: [ + {start: 1, end: 1, result: "ca.1"}, + ], + }, + // Approximation sign can be a word. + "ja": { + options: {}, + ranges: [ + {start: 1, end: 1, result: "約1"}, + ], + }, +}; + +for (let [locale, {options, ranges}] of Object.entries(tests)) { + let nf = new Intl.NumberFormat(locale, options); + for (let {start, end, result} of ranges) { + assertEq(nf.formatRange(start, end), result, `${start}-${end}`); + assertEq(nf.formatRangeToParts(start, end).reduce((acc, part) => acc + part.value, ""), + result, `${start}-${end}`); + } +} + +// Throws an error if either value is NaN. +{ + const errorTests = [ + {start: NaN, end: NaN}, + {start: 0, end: NaN}, + {start: NaN, end: 0}, + {start: Infinity, end: NaN}, + {start: NaN, end: Infinity}, + ]; + + let nf = new Intl.NumberFormat("en"); + for (let {start, end} of errorTests) { + assertThrowsInstanceOf(() => nf.formatRange(start, end), RangeError); + assertThrowsInstanceOf(() => nf.formatRangeToParts(start, end), RangeError); + } +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-compact.js b/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-compact.js new file mode 100644 index 0000000000..dea7c40642 --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-compact.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +if (typeof getAvailableLocalesOf === "undefined") { + var getAvailableLocalesOf = SpecialPowers.Cu.getJSTestingFunctions().getAvailableLocalesOf; +} + +const numbers = [ + 0, 1, 2, 5, 10, 100, 1000, 10_000, 100_000, 1_000_000, + 0.1, 0.2, 0.5, 1.5, + -0, -1, -2, -5, + Infinity, -Infinity, +]; + +const options = {notation: "compact"}; + +// List of known approximately sign in CLDR 40. +const approximatelySigns = [ + "~", "∼", "≈", "≃", "ca.", "約", "dáàṣì", "dáàshì", +]; + +// Iterate over all locales and ensure we find exactly one approximately sign. +for (let locale of getAvailableLocalesOf("NumberFormat").sort()) { + let nf = new Intl.NumberFormat(locale, options); + for (let number of numbers) { + let parts = nf.formatRangeToParts(number, number); + let approx = parts.filter(part => part.type === "approximatelySign"); + + assertEq(approx.length, 1); + assertEq(approximatelySigns.some(approxSign => approx[0].value.includes(approxSign)), true); + } +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-currency.js b/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-currency.js new file mode 100644 index 0000000000..4855b9ca00 --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-currency.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +if (typeof getAvailableLocalesOf === "undefined") { + var getAvailableLocalesOf = SpecialPowers.Cu.getJSTestingFunctions().getAvailableLocalesOf; +} + +const numbers = [ + 0, 1, 2, 5, 10, 100, 1000, 10_000, 100_000, 1_000_000, + 0.1, 0.2, 0.5, 1.5, + -0, -1, -2, -5, + Infinity, -Infinity, +]; + +const options = {style: "currency", currency: "EUR"}; + +// List of known approximately sign in CLDR 40. +const approximatelySigns = [ + "~", "∼", "≈", "≃", "ca.", "約", "dáàṣì", "dáàshì", +]; + +// Iterate over all locales and ensure we find exactly one approximately sign. +for (let locale of getAvailableLocalesOf("NumberFormat").sort()) { + let nf = new Intl.NumberFormat(locale, options); + for (let number of numbers) { + let parts = nf.formatRangeToParts(number, number); + let approx = parts.filter(part => part.type === "approximatelySign"); + + assertEq(approx.length, 1); + assertEq(approximatelySigns.some(approxSign => approx[0].value.includes(approxSign)), true); + } +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-percent.js b/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-percent.js new file mode 100644 index 0000000000..abdd3de083 --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-percent.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +if (typeof getAvailableLocalesOf === "undefined") { + var getAvailableLocalesOf = SpecialPowers.Cu.getJSTestingFunctions().getAvailableLocalesOf; +} + +const numbers = [ + 0, 1, 2, 5, 10, 100, 1000, 10_000, 100_000, 1_000_000, + 0.1, 0.2, 0.5, 1.5, + -0, -1, -2, -5, + Infinity, -Infinity, +]; + +const options = {style: "percent"}; + +// List of known approximately sign in CLDR 40. +const approximatelySigns = [ + "~", "∼", "≈", "≃", "ca.", "約", "dáàṣì", "dáàshì", +]; + +// Iterate over all locales and ensure we find exactly one approximately sign. +for (let locale of getAvailableLocalesOf("NumberFormat").sort()) { + let nf = new Intl.NumberFormat(locale, options); + for (let number of numbers) { + let parts = nf.formatRangeToParts(number, number); + let approx = parts.filter(part => part.type === "approximatelySign"); + + assertEq(approx.length, 1); + assertEq(approximatelySigns.some(approxSign => approx[0].value.includes(approxSign)), true); + } +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-signDisplay.js b/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-signDisplay.js new file mode 100644 index 0000000000..92d8251f6a --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-signDisplay.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +if (typeof getAvailableLocalesOf === "undefined") { + var getAvailableLocalesOf = SpecialPowers.Cu.getJSTestingFunctions().getAvailableLocalesOf; +} + +const numbers = [ + 0, 1, 2, 5, 10, 100, 1000, 10_000, 100_000, 1_000_000, + 0.1, 0.2, 0.5, 1.5, + -0, -1, -2, -5, + Infinity, -Infinity, +]; + +const options = {signDisplay: "always"}; + +// List of known approximately sign in CLDR 40. +const approximatelySigns = [ + "~", "∼", "≈", "≃", "ca.", "約", "dáàṣì", "dáàshì", +]; + +// Iterate over all locales and ensure we find exactly one approximately sign. +for (let locale of getAvailableLocalesOf("NumberFormat").sort()) { + let nf = new Intl.NumberFormat(locale, options); + for (let number of numbers) { + let parts = nf.formatRangeToParts(number, number); + let approx = parts.filter(part => part.type === "approximatelySign"); + + assertEq(approx.length, 1); + assertEq(approximatelySigns.some(approxSign => approx[0].value.includes(approxSign)), true); + } +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-unit.js b/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-unit.js new file mode 100644 index 0000000000..c66dbfb462 --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign-unit.js @@ -0,0 +1,41 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +if (typeof getAvailableLocalesOf === "undefined") { + var getAvailableLocalesOf = SpecialPowers.Cu.getJSTestingFunctions().getAvailableLocalesOf; +} + +const numbers = [ + 0, 1, 2, 5, 10, 100, 1000, 10_000, 100_000, 1_000_000, + 0.1, 0.2, 0.5, 1.5, + -0, -1, -2, -5, + Infinity, -Infinity, +]; + +const options = {style: "unit", unit: "meter"}; + +// List of known approximately sign in CLDR 40. +const approximatelySigns = [ + "~", "∼", "≈", "≃", "ca.", "約", "dáàṣì", "dáàshì", +]; + +// Iterate over all locales and ensure we find exactly one approximately sign. +for (let locale of getAvailableLocalesOf("NumberFormat").sort()) { + let nf = new Intl.NumberFormat(locale, options); + for (let number of numbers) { + let parts = nf.formatRangeToParts(number, number); + let approx = parts.filter(part => part.type === "approximatelySign"); + + // Known failure case. + // - https://github.com/tc39/proposal-intl-numberformat-v3/issues/64 + // - https://unicode-org.atlassian.net/browse/CLDR-14918 + if (approx.length === 0 && new Intl.Locale(locale).language === "ar") { + continue; + } + + assertEq(approx.length, 1); + assertEq(approximatelySigns.some(approxSign => approx[0].value.includes(approxSign)), true); + } +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign.js b/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign.js new file mode 100644 index 0000000000..cab6e5c3d5 --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts-approximately-sign.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +if (typeof getAvailableLocalesOf === "undefined") { + var getAvailableLocalesOf = SpecialPowers.Cu.getJSTestingFunctions().getAvailableLocalesOf; +} + +const numbers = [ + 0, 1, 2, 5, 10, 100, 1000, 10_000, 100_000, 1_000_000, + 0.1, 0.2, 0.5, 1.5, + -0, -1, -2, -5, + Infinity, -Infinity, +]; + +const options = {}; + +// List of known approximately sign in CLDR 40. +const approximatelySigns = [ + "~", "∼", "≈", "≃", "ca.", "約", "dáàṣì", "dáàshì", +]; + +// Iterate over all locales and ensure we find exactly one approximately sign. +for (let locale of getAvailableLocalesOf("NumberFormat").sort()) { + let nf = new Intl.NumberFormat(locale, options); + for (let number of numbers) { + let parts = nf.formatRangeToParts(number, number); + let approx = parts.filter(part => part.type === "approximatelySign"); + + assertEq(approx.length, 1); + assertEq(approximatelySigns.some(approxSign => approx[0].value.includes(approxSign)), true); + } +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts.js b/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts.js new file mode 100644 index 0000000000..fba5388973 --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/formatRangeToParts.js @@ -0,0 +1,174 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const Start = NumberRangeFormatParts("startRange"); +const End = NumberRangeFormatParts("endRange"); +const Shared = NumberRangeFormatParts("shared"); + +const tests = { + "en": { + options: {}, + ranges: [ + // Approximation sign present. + { + start: 0, + end: 0, + result: [Shared.Approx("~"), Shared.Integer("0")], + }, + { + start: -0, + end: -0, + result: [Shared.Approx("~"), Shared.MinusSign("-"), Shared.Integer("0")], + }, + { + start: -1, + end: -1, + result: [Shared.Approx("~"), Shared.MinusSign("-"), Shared.Integer("1")], + }, + { + start: 0.5, + end: 0.5, + result: [Shared.Approx("~"), Shared.Integer("0"), Shared.Decimal("."), Shared.Fraction("5")], + }, + { + start: Infinity, + end: Infinity, + result: [Shared.Approx("~"), Shared.Inf("∞")], + }, + { + start: -Infinity, + end: -Infinity, + result: [Shared.Approx("~"), Shared.MinusSign("-"), Shared.Inf("∞")], + }, + + // Proper ranges. + { + start: -2, + end: -1, + result: [Start.MinusSign("-"), Start.Integer("2"), Shared.Literal(" – "), End.MinusSign("-"), End.Integer("1")], + }, + { + start: -1, + end: 1, + result: [Start.MinusSign("-"), Start.Integer("1"), Shared.Literal(" – "), End.Integer("1")], + }, + { + start: 1, + end: 2, + result: [Start.Integer("1"), Shared.Literal("–"), End.Integer("2")], + }, + ], + }, + // Non-ASCII digits. + "ar": { + options: {}, + ranges: [ + { + start: -2, + end: -1, + result: [Shared.Literal("\u061C"), Shared.MinusSign("-"), Start.Integer("٢"), Shared.Literal("–"), End.Integer("١")], + }, + { + start: -1, + end: -1, + result: [Shared.Approx("~"), Shared.Literal("\u061C"), Shared.MinusSign("-"), Shared.Integer("١")], + }, + { + start: -1, + end: 0, + result: [Start.Literal("\u061C"), Start.MinusSign("-"), Start.Integer("١"), Shared.Literal(" – "), End.Integer("٠")], + }, + { + start: 0, + end: 0, + result: [Shared.Approx("~"), Shared.Integer("٠")], + }, + { + start: 0, + end: 1, + result: [Start.Integer("٠"), Shared.Literal("–"), End.Integer("١")], + }, + { + start: 1, + end: 1, + result: [Shared.Approx("~"), Shared.Integer("١")], + }, + { + start: 1, + end: 2, + result: [Start.Integer("١"), Shared.Literal("–"), End.Integer("٢")], + }, + ], + }, + "th-u-nu-thai": { + options: {}, + ranges: [ + { + start: -2, + end: -1, + result: [Start.MinusSign("-"), Start.Integer("๒"), Shared.Literal(" - "), End.MinusSign("-"), End.Integer("๑")], + }, + { + start: -1, + end: -1, + result: [Shared.Approx("~"), Shared.MinusSign("-"), Shared.Integer("๑")], + }, + { + start: -1, + end: 0, + result: [Start.MinusSign("-"), Start.Integer("๑"), Shared.Literal(" - "), End.Integer("๐")], + }, + { + start: 0, + end: 0, + result: [Shared.Approx("~"), Shared.Integer("๐")], + }, + { + start: 0, + end: 1, + result: [Start.Integer("๐"), Shared.Literal("-"), End.Integer("๑")], + }, + { + start: 1, + end: 1, + result: [Shared.Approx("~"), Shared.Integer("๑")], + }, + { + start: 1, + end: 2, + result: [Start.Integer("๑"), Shared.Literal("-"), End.Integer("๒")], + }, + ], + }, + // Approximation sign may consist of multiple characters. + "no": { + options: {}, + ranges: [ + { + start: 1, + end: 1, + result: [Shared.Approx("ca."), Shared.Integer("1")], + }, + ], + }, + // Approximation sign can be a word. + "ja": { + options: {}, + ranges: [ + { + start: 1, + end: 1, + result: [Shared.Approx("約"), Shared.Integer("1")], + }, + ], + }, +}; + +for (let [locale, {options, ranges}] of Object.entries(tests)) { + let nf = new Intl.NumberFormat(locale, options); + for (let {start, end, result} of ranges) { + assertRangeParts(nf, start, end, result); + } +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/formatToParts.js b/js/src/tests/non262/Intl/NumberFormat/formatToParts.js new file mode 100644 index 0000000000..3ac7c3f4d3 --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/formatToParts.js @@ -0,0 +1,357 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 1289882; +var summary = "Implement Intl.NumberFormat.prototype.formatToParts"; + +print(BUGNUMBER + ": " + summary); + +//----------------------------------------------------------------------------- + +assertEq("formatToParts" in Intl.NumberFormat(), true); + +// NOTE: Some of these tests exercise standard behavior (e.g. that format and +// formatToParts expose the same formatted string). But much of this, +// like the exact-formatted-string expectations, is technically +// implementation-dependent. This is necessary as a practical matter to +// properly test the conversion from ICU's nested-field exposure to +// ECMA-402's sequential-parts exposure. + +var { + Nan, Inf, Integer, Group, Decimal, Fraction, + MinusSign, PlusSign, PercentSign, Currency, Literal, +} = NumberFormatParts; + +//----------------------------------------------------------------------------- + +// Test -0's partitioning now that it's not treated like +0. +// https://github.com/tc39/ecma402/pull/232 + +var deadSimpleFormatter = new Intl.NumberFormat("en-US"); + +assertParts(deadSimpleFormatter, -0, + [MinusSign("-"), Integer("0")]); + +// Test behavior of a currency with code formatting. +var usdCodeOptions = + { + style: "currency", + currency: "USD", + currencyDisplay: "code", + minimumFractionDigits: 0, + maximumFractionDigits: 0, + }; +var usDollarsCode = new Intl.NumberFormat("en-US", usdCodeOptions); + +assertParts(usDollarsCode, 25, + [Currency("USD"), Literal("\xA0"), Integer("25")]); + +// ISO 4217 currency codes are formed from an ISO 3166-1 alpha-2 country code +// followed by a third letter. ISO 3166 guarantees that no country code +// starting with "X" will ever be assigned. Stepping carefully around a few +// 4217-designated special "currencies", XQQ will never have a representation. +// Thus, yes: this really is specified to work, as unrecognized or unsupported +// codes pass into the string unmodified. +var xqqCodeOptions = + { + style: "currency", + currency: "XQQ", + currencyDisplay: "code", + minimumFractionDigits: 0, + maximumFractionDigits: 0, + }; +var xqqMoneyCode = new Intl.NumberFormat("en-US", xqqCodeOptions); + +assertParts(xqqMoneyCode, 25, + [Currency("XQQ"), Literal("\xA0"), Integer("25")]); + +// Test currencyDisplay: "name". +var usdNameOptions = + { + style: "currency", + currency: "USD", + currencyDisplay: "name", + minimumFractionDigits: 0, + maximumFractionDigits: 0, + }; +var usDollarsName = new Intl.NumberFormat("en-US", usdNameOptions); + +assertParts(usDollarsName, 25, + [Integer("25"), Literal(" "), Currency("US dollars")]); + +var usdNameGroupingOptions = + { + style: "currency", + currency: "USD", + currencyDisplay: "name", + minimumFractionDigits: 0, + maximumFractionDigits: 0, + }; +var usDollarsNameGrouping = + new Intl.NumberFormat("en-US", usdNameGroupingOptions); + +assertParts(usDollarsNameGrouping, 12345678, + [Integer("12"), + Group(","), + Integer("345"), + Group(","), + Integer("678"), + Literal(" "), + Currency("US dollars")]); + +// But if the implementation doesn't recognize the currency, the provided code +// is used in place of a proper name, unmolested. +var xqqNameOptions = + { + style: "currency", + currency: "XQQ", + currencyDisplay: "name", + minimumFractionDigits: 0, + maximumFractionDigits: 0, + }; +var xqqMoneyName = new Intl.NumberFormat("en-US", xqqNameOptions); + +assertParts(xqqMoneyName, 25, + [Integer("25"), Literal(" "), Currency("XQQ")]); + +// Test some currencies with fractional components. + +var usdNameFractionOptions = + { + style: "currency", + currency: "USD", + currencyDisplay: "name", + minimumFractionDigits: 2, + maximumFractionDigits: 2, + }; +var usdNameFractionFormatter = + new Intl.NumberFormat("en-US", usdNameFractionOptions); + +// The US national surplus (i.e. debt) as of October 18, 2016. (Replicating +// data from a comment in builtin/Intl/NumberFormat.cpp.) +var usNationalSurplus = -19766580028249.41; + +assertParts(usdNameFractionFormatter, usNationalSurplus, + [MinusSign("-"), + Integer("19"), + Group(","), + Integer("766"), + Group(","), + Integer("580"), + Group(","), + Integer("028"), + Group(","), + Integer("249"), + Decimal("."), + Fraction("41"), + Literal(" "), + Currency("US dollars")]); + +// Percents in various forms. + +var usPercentOptions = + { + style: "percent", + minimumFractionDigits: 1, + maximumFractionDigits: 1, + }; +var usPercentFormatter = + new Intl.NumberFormat("en-US", usPercentOptions); + +assertParts(usPercentFormatter, 0.375, + [Integer("37"), Decimal("."), Fraction("5"), PercentSign("%")]); + +assertParts(usPercentFormatter, -1284.375, + [MinusSign("-"), + Integer("128"), + Group(","), + Integer("437"), + Decimal("."), + Fraction("5"), + PercentSign("%")]); + +assertParts(usPercentFormatter, NaN, + [Nan("NaN"), PercentSign("%")]); + +assertParts(usPercentFormatter, Infinity, + [Inf("∞"), PercentSign("%")]); + +assertParts(usPercentFormatter, -Infinity, + [MinusSign("-"), Inf("∞"), PercentSign("%")]); + +var dePercentOptions = + { + style: "percent", + minimumFractionDigits: 1, + maximumFractionDigits: 1, + }; +var dePercentFormatter = + new Intl.NumberFormat("de", dePercentOptions); + +assertParts(dePercentFormatter, 0.375, + [Integer("37"), Decimal(","), Fraction("5"), Literal("\xA0"), PercentSign("%")]); + +assertParts(dePercentFormatter, -1284.375, + [MinusSign("-"), + Integer("128"), + Group("."), + Integer("437"), + Decimal(","), + Fraction("5"), + Literal("\xA0"), + PercentSign("%")]); + +assertParts(dePercentFormatter, NaN, + [Nan("NaN"), Literal("\xA0"), PercentSign("%")]); + +assertParts(dePercentFormatter, Infinity, + [Inf("∞"), Literal("\xA0"), PercentSign("%")]); + +assertParts(dePercentFormatter, -Infinity, + [MinusSign("-"), Inf("∞"), Literal("\xA0"), PercentSign("%")]); + +var arPercentOptions = + { + style: "percent", + minimumFractionDigits: 2, + }; +var arPercentFormatter = + new Intl.NumberFormat("ar-IQ", arPercentOptions); + +assertParts(arPercentFormatter, -135.32, + [Literal("\u{061C}"), + MinusSign("-"), + Integer("١٣"), + Group("٬"), + Integer("٥٣٢"), + Decimal("٫"), + Fraction("٠٠"), + PercentSign("٪"), + Literal("\u{061C}")]); + +// Decimals. + +var usDecimalOptions = + { + style: "decimal", + maximumFractionDigits: 7 // minimum defaults to 0 + }; +var usDecimalFormatter = + new Intl.NumberFormat("en-US", usDecimalOptions); + +assertParts(usDecimalFormatter, 42, + [Integer("42")]); + +assertParts(usDecimalFormatter, 1337, + [Integer("1"), Group(","), Integer("337")]); + +assertParts(usDecimalFormatter, -6.25, + [MinusSign("-"), Integer("6"), Decimal("."), Fraction("25")]); + +assertParts(usDecimalFormatter, -1376.25, + [MinusSign("-"), + Integer("1"), + Group(","), + Integer("376"), + Decimal("."), + Fraction("25")]); + +assertParts(usDecimalFormatter, 124816.8359375, + [Integer("124"), + Group(","), + Integer("816"), + Decimal("."), + Fraction("8359375")]); + +var usNoGroupingDecimalOptions = + { + style: "decimal", + useGrouping: false, + maximumFractionDigits: 7 // minimum defaults to 0 + }; +var usNoGroupingDecimalFormatter = + new Intl.NumberFormat("en-US", usNoGroupingDecimalOptions); + +assertParts(usNoGroupingDecimalFormatter, 1337, + [Integer("1337")]); + +assertParts(usNoGroupingDecimalFormatter, -6.25, + [MinusSign("-"), Integer("6"), Decimal("."), Fraction("25")]); + +assertParts(usNoGroupingDecimalFormatter, -1376.25, + [MinusSign("-"), + Integer("1376"), + Decimal("."), + Fraction("25")]); + +assertParts(usNoGroupingDecimalFormatter, 124816.8359375, + [Integer("124816"), + Decimal("."), + Fraction("8359375")]); + +var deDecimalOptions = + { + style: "decimal", + maximumFractionDigits: 7 // minimum defaults to 0 + }; +var deDecimalFormatter = + new Intl.NumberFormat("de-DE", deDecimalOptions); + +assertParts(deDecimalFormatter, 42, + [Integer("42")]); + +assertParts(deDecimalFormatter, 1337, + [Integer("1"), Group("."), Integer("337")]); + +assertParts(deDecimalFormatter, -6.25, + [MinusSign("-"), Integer("6"), Decimal(","), Fraction("25")]); + +assertParts(deDecimalFormatter, -1376.25, + [MinusSign("-"), + Integer("1"), + Group("."), + Integer("376"), + Decimal(","), + Fraction("25")]); + +assertParts(deDecimalFormatter, 124816.8359375, + [Integer("124"), + Group("."), + Integer("816"), + Decimal(","), + Fraction("8359375")]); + +var deNoGroupingDecimalOptions = + { + style: "decimal", + useGrouping: false, + maximumFractionDigits: 7 // minimum defaults to 0 + }; +var deNoGroupingDecimalFormatter = + new Intl.NumberFormat("de-DE", deNoGroupingDecimalOptions); + +assertParts(deNoGroupingDecimalFormatter, 1337, + [Integer("1337")]); + +assertParts(deNoGroupingDecimalFormatter, -6.25, + [MinusSign("-"), Integer("6"), Decimal(","), Fraction("25")]); + +assertParts(deNoGroupingDecimalFormatter, -1376.25, + [MinusSign("-"), + Integer("1376"), + Decimal(","), + Fraction("25")]); + +assertParts(deNoGroupingDecimalFormatter, 124816.8359375, + [Integer("124816"), + Decimal(","), + Fraction("8359375")]); + +//----------------------------------------------------------------------------- + +if (typeof reportCompare === "function") + reportCompare(0, 0, 'ok'); + +print("Tests complete"); diff --git a/js/src/tests/non262/Intl/NumberFormat/formatting-NaN.js b/js/src/tests/non262/Intl/NumberFormat/formatting-NaN.js new file mode 100644 index 0000000000..430d74222e --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/formatting-NaN.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 1484943; +var summary = "Don't crash doing format/formatToParts on -NaN"; + +print(BUGNUMBER + ": " + summary); + +//----------------------------------------------------------------------------- + +assertEq("formatToParts" in Intl.NumberFormat(), true); + +var nf = new Intl.NumberFormat("en-US"); +var parts; + +var values = [NaN, -NaN]; + +for (var v of values) +{ + assertEq(nf.format(v), "NaN"); + + parts = nf.formatToParts(v); + assertEq(parts.length, 1); + assertEq(parts[0].type, "nan"); + assertEq(parts[0].value, "NaN"); +} + +//----------------------------------------------------------------------------- + +if (typeof reportCompare === "function") + reportCompare(0, 0, 'ok'); + +print("Tests complete"); diff --git a/js/src/tests/non262/Intl/NumberFormat/negativeZeroFractionDigits.js b/js/src/tests/non262/Intl/NumberFormat/negativeZeroFractionDigits.js new file mode 100644 index 0000000000..0db461f50e --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/negativeZeroFractionDigits.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const optionsList = [ + {minimumFractionDigits: -0, maximumFractionDigits: -0}, + {minimumFractionDigits: -0, maximumFractionDigits: +0}, + {minimumFractionDigits: +0, maximumFractionDigits: -0}, + {minimumFractionDigits: +0, maximumFractionDigits: +0}, +]; + +for (let options of optionsList) { + let numberFormat = new Intl.NumberFormat("en-US", options); + + let {minimumFractionDigits, maximumFractionDigits} = numberFormat.resolvedOptions(); + assertEq(minimumFractionDigits, +0); + assertEq(maximumFractionDigits, +0); + + assertEq(numberFormat.format(123), "123"); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/notation-compact-long.js b/js/src/tests/non262/Intl/NumberFormat/notation-compact-long.js new file mode 100644 index 0000000000..80c3416afb --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/notation-compact-long.js @@ -0,0 +1,139 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const { + Nan, Inf, Integer, MinusSign, PlusSign, Decimal, Fraction, Group, Literal, + Compact, +} = NumberFormatParts; + +const testcases = [ + { + locale: "en", + options: { + notation: "compact", + compactDisplay: "long", + }, + values: [ + {value: +0, string: "0", parts: [Integer("0")]}, + {value: -0, string: "-0", parts: [MinusSign("-"), Integer("0")]}, + {value: 0n, string: "0", parts: [Integer("0")]}, + + {value: 1, string: "1", parts: [Integer("1")]}, + {value: 10, string: "10", parts: [Integer("10")]}, + {value: 100, string: "100", parts: [Integer("100")]}, + {value: 1000, string: "1 thousand", parts: [Integer("1"), Literal(" "), Compact("thousand")]}, + {value: 10000, string: "10 thousand", parts: [Integer("10"), Literal(" "), Compact("thousand")]}, + {value: 100000, string: "100 thousand", parts: [Integer("100"), Literal(" "), Compact("thousand")]}, + {value: 1000000, string: "1 million", parts: [Integer("1"), Literal(" "), Compact("million")]}, + {value: 10000000, string: "10 million", parts: [Integer("10"), Literal(" "), Compact("million")]}, + {value: 100000000, string: "100 million", parts: [Integer("100"), Literal(" "), Compact("million")]}, + {value: 1000000000, string: "1 billion", parts: [Integer("1"), Literal(" "), Compact("billion")]}, + {value: 10000000000, string: "10 billion", parts: [Integer("10"), Literal(" "), Compact("billion")]}, + {value: 100000000000, string: "100 billion", parts: [Integer("100"), Literal(" "), Compact("billion")]}, + {value: 1000000000000, string: "1 trillion", parts: [Integer("1"), Literal(" "), Compact("trillion")]}, + {value: 10000000000000, string: "10 trillion", parts: [Integer("10"), Literal(" "), Compact("trillion")]}, + {value: 100000000000000, string: "100 trillion", parts: [Integer("100"), Literal(" "), Compact("trillion")]}, + {value: 1000000000000000, string: "1000 trillion", parts: [Integer("1000"), Literal(" "), Compact("trillion")]}, + {value: 10000000000000000, string: "10,000 trillion", parts: [Integer("10"), Group(","), Integer("000"), Literal(" "), Compact("trillion")]}, + {value: 100000000000000000, string: "100,000 trillion", parts: [Integer("100"), Group(","), Integer("000"), Literal(" "), Compact("trillion")]}, + + {value: 1n, string: "1", parts: [Integer("1")]}, + {value: 10n, string: "10", parts: [Integer("10")]}, + {value: 100n, string: "100", parts: [Integer("100")]}, + {value: 1000n, string: "1 thousand", parts: [Integer("1"), Literal(" "), Compact("thousand")]}, + {value: 10000n, string: "10 thousand", parts: [Integer("10"), Literal(" "), Compact("thousand")]}, + {value: 100000n, string: "100 thousand", parts: [Integer("100"), Literal(" "), Compact("thousand")]}, + {value: 1000000n, string: "1 million", parts: [Integer("1"), Literal(" "), Compact("million")]}, + {value: 10000000n, string: "10 million", parts: [Integer("10"), Literal(" "), Compact("million")]}, + {value: 100000000n, string: "100 million", parts: [Integer("100"), Literal(" "), Compact("million")]}, + {value: 1000000000n, string: "1 billion", parts: [Integer("1"), Literal(" "), Compact("billion")]}, + {value: 10000000000n, string: "10 billion", parts: [Integer("10"), Literal(" "), Compact("billion")]}, + {value: 100000000000n, string: "100 billion", parts: [Integer("100"), Literal(" "), Compact("billion")]}, + {value: 1000000000000n, string: "1 trillion", parts: [Integer("1"), Literal(" "), Compact("trillion")]}, + {value: 10000000000000n, string: "10 trillion", parts: [Integer("10"), Literal(" "), Compact("trillion")]}, + {value: 100000000000000n, string: "100 trillion", parts: [Integer("100"), Literal(" "), Compact("trillion")]}, + {value: 1000000000000000n, string: "1000 trillion", parts: [Integer("1000"), Literal(" "), Compact("trillion")]}, + {value: 10000000000000000n, string: "10,000 trillion", parts: [Integer("10"), Group(","), Integer("000"), Literal(" "), Compact("trillion")]}, + {value: 100000000000000000n, string: "100,000 trillion", parts: [Integer("100"), Group(","), Integer("000"), Literal(" "), Compact("trillion")]}, + + {value: 0.1, string: "0.1", parts: [Integer("0"), Decimal("."), Fraction("1")]}, + {value: 0.01, string: "0.01", parts: [Integer("0"), Decimal("."), Fraction("01")]}, + {value: 0.001, string: "0.001", parts: [Integer("0"), Decimal("."), Fraction("001")]}, + {value: 0.0001, string: "0.0001", parts: [Integer("0"), Decimal("."), Fraction("0001")]}, + {value: 0.00001, string: "0.00001", parts: [Integer("0"), Decimal("."), Fraction("00001")]}, + {value: 0.000001, string: "0.000001", parts: [Integer("0"), Decimal("."), Fraction("000001")]}, + {value: 0.0000001, string: "0.0000001", parts: [Integer("0"), Decimal("."), Fraction("0000001")]}, + + {value: 12, string: "12", parts: [Integer("12")]}, + {value: 123, string: "123", parts: [Integer("123")]}, + {value: 1234, string: "1.2 thousand", parts: [Integer("1"), Decimal("."), Fraction("2"), Literal(" "), Compact("thousand")]}, + {value: 12345, string: "12 thousand", parts: [Integer("12"), Literal(" "), Compact("thousand")]}, + {value: 123456, string: "123 thousand", parts: [Integer("123"), Literal(" "), Compact("thousand")]}, + {value: 1234567, string: "1.2 million", parts: [Integer("1"), Decimal("."), Fraction("2"), Literal(" "), Compact("million")]}, + {value: 12345678, string: "12 million", parts: [Integer("12"), Literal(" "), Compact("million")]}, + {value: 123456789, string: "123 million", parts: [Integer("123"), Literal(" "), Compact("million")]}, + + {value: Infinity, string: "∞", parts: [Inf("∞")]}, + {value: -Infinity, string: "-∞", parts: [MinusSign("-"), Inf("∞")]}, + + {value: NaN, string: "NaN", parts: [Nan("NaN")]}, + {value: -NaN, string: "NaN", parts: [Nan("NaN")]}, + ], + }, + + // The "{compactName}" placeholder may have different plural forms. + { + locale: "de", + options: { + notation: "compact", + compactDisplay: "long", + }, + values: [ + {value: 1e6, string: "1 Million", parts: [Integer("1"), Literal(" "), Compact("Million")]}, + {value: 2e6, string: "2 Millionen", parts: [Integer("2"), Literal(" "), Compact("Millionen")]}, + {value: 1e9, string: "1 Milliarde", parts: [Integer("1"), Literal(" "), Compact("Milliarde")]}, + {value: 2e9, string: "2 Milliarden", parts: [Integer("2"), Literal(" "), Compact("Milliarden")]}, + ], + }, + + // Digits are grouped in myriads (every 10,000) in Japanese. + { + locale: "ja", + options: { + notation: "compact", + compactDisplay: "long", + }, + values: [ + {value: 1, string: "1", parts: [Integer("1")]}, + {value: 10, string: "10", parts: [Integer("10")]}, + {value: 100, string: "100", parts: [Integer("100")]}, + {value: 1000, string: "1000", parts: [Integer("1000")]}, + + {value: 10e3, string: "1\u4E07", parts: [Integer("1"), Compact("\u4E07")]}, + {value: 100e3, string: "10\u4E07", parts: [Integer("10"), Compact("\u4E07")]}, + {value: 1000e3, string: "100\u4E07", parts: [Integer("100"), Compact("\u4E07")]}, + {value: 10000e3, string: "1000\u4E07", parts: [Integer("1000"), Compact("\u4E07")]}, + + {value: 10e7, string: "1\u5104", parts: [Integer("1"), Compact("\u5104")]}, + {value: 100e7, string: "10\u5104", parts: [Integer("10"), Compact("\u5104")]}, + {value: 1000e7, string: "100\u5104", parts: [Integer("100"), Compact("\u5104")]}, + {value: 10000e7, string: "1000\u5104", parts: [Integer("1000"), Compact("\u5104")]}, + + {value: 10e11, string: "1\u5146", parts: [Integer("1"), Compact("\u5146")]}, + {value: 100e11, string: "10\u5146", parts: [Integer("10"), Compact("\u5146")]}, + {value: 1000e11, string: "100\u5146", parts: [Integer("100"), Compact("\u5146")]}, + {value: 10000e11, string: "1000\u5146", parts: [Integer("1000"), Compact("\u5146")]}, + + {value: 10e15, string: "1\u4EAC", parts: [Integer("1"), Compact("\u4EAC")]}, + {value: 100e15, string: "10\u4EAC", parts: [Integer("10"), Compact("\u4EAC")]}, + {value: 1000e15, string: "100\u4EAC", parts: [Integer("100"), Compact("\u4EAC")]}, + {value: 10000e15, string: "1000\u4EAC", parts: [Integer("1000"), Compact("\u4EAC")]}, + + {value: 100000e15, string: "10,000\u4EAC", parts: [Integer("10"), Group(","), Integer("000"), Compact("\u4EAC")]}, + ], + }, +]; + +runNumberFormattingTestcases(testcases); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/notation-compact-short.js b/js/src/tests/non262/Intl/NumberFormat/notation-compact-short.js new file mode 100644 index 0000000000..f3a546294d --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/notation-compact-short.js @@ -0,0 +1,136 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const { + Nan, Inf, Integer, MinusSign, PlusSign, Decimal, Fraction, Group, Literal, + Compact, +} = NumberFormatParts; + +const testcases = [ + { + locale: "en", + options: { + notation: "compact", + compactDisplay: "short", + }, + values: [ + {value: +0, string: "0", parts: [Integer("0")]}, + {value: -0, string: "-0", parts: [MinusSign("-"), Integer("0")]}, + {value: 0n, string: "0", parts: [Integer("0")]}, + + {value: 1, string: "1", parts: [Integer("1")]}, + {value: 10, string: "10", parts: [Integer("10")]}, + {value: 100, string: "100", parts: [Integer("100")]}, + {value: 1000, string: "1K", parts: [Integer("1"), Compact("K")]}, + {value: 10000, string: "10K", parts: [Integer("10"), Compact("K")]}, + {value: 100000, string: "100K", parts: [Integer("100"), Compact("K")]}, + {value: 1000000, string: "1M", parts: [Integer("1"), Compact("M")]}, + {value: 10000000, string: "10M", parts: [Integer("10"), Compact("M")]}, + {value: 100000000, string: "100M", parts: [Integer("100"), Compact("M")]}, + {value: 1000000000, string: "1B", parts: [Integer("1"), Compact("B")]}, + {value: 10000000000, string: "10B", parts: [Integer("10"), Compact("B")]}, + {value: 100000000000, string: "100B", parts: [Integer("100"), Compact("B")]}, + {value: 1000000000000, string: "1T", parts: [Integer("1"), Compact("T")]}, + {value: 10000000000000, string: "10T", parts: [Integer("10"), Compact("T")]}, + {value: 100000000000000, string: "100T", parts: [Integer("100"), Compact("T")]}, + {value: 1000000000000000, string: "1000T", parts: [Integer("1000"), Compact("T")]}, + {value: 10000000000000000, string: "10,000T", parts: [Integer("10"), Group(","), Integer("000"), Compact("T")]}, + {value: 100000000000000000, string: "100,000T", parts: [Integer("100"), Group(","), Integer("000"), Compact("T")]}, + + {value: 1n, string: "1", parts: [Integer("1")]}, + {value: 10n, string: "10", parts: [Integer("10")]}, + {value: 100n, string: "100", parts: [Integer("100")]}, + {value: 1000n, string: "1K", parts: [Integer("1"), Compact("K")]}, + {value: 10000n, string: "10K", parts: [Integer("10"), Compact("K")]}, + {value: 100000n, string: "100K", parts: [Integer("100"), Compact("K")]}, + {value: 1000000n, string: "1M", parts: [Integer("1"), Compact("M")]}, + {value: 10000000n, string: "10M", parts: [Integer("10"), Compact("M")]}, + {value: 100000000n, string: "100M", parts: [Integer("100"), Compact("M")]}, + {value: 1000000000n, string: "1B", parts: [Integer("1"), Compact("B")]}, + {value: 10000000000n, string: "10B", parts: [Integer("10"), Compact("B")]}, + {value: 100000000000n, string: "100B", parts: [Integer("100"), Compact("B")]}, + {value: 1000000000000n, string: "1T", parts: [Integer("1"), Compact("T")]}, + {value: 10000000000000n, string: "10T", parts: [Integer("10"), Compact("T")]}, + {value: 100000000000000n, string: "100T", parts: [Integer("100"), Compact("T")]}, + {value: 1000000000000000n, string: "1000T", parts: [Integer("1000"), Compact("T")]}, + {value: 10000000000000000n, string: "10,000T", parts: [Integer("10"), Group(","), Integer("000"), Compact("T")]}, + {value: 100000000000000000n, string: "100,000T", parts: [Integer("100"), Group(","), Integer("000"), Compact("T")]}, + + {value: 0.1, string: "0.1", parts: [Integer("0"), Decimal("."), Fraction("1")]}, + {value: 0.01, string: "0.01", parts: [Integer("0"), Decimal("."), Fraction("01")]}, + {value: 0.001, string: "0.001", parts: [Integer("0"), Decimal("."), Fraction("001")]}, + {value: 0.0001, string: "0.0001", parts: [Integer("0"), Decimal("."), Fraction("0001")]}, + {value: 0.00001, string: "0.00001", parts: [Integer("0"), Decimal("."), Fraction("00001")]}, + {value: 0.000001, string: "0.000001", parts: [Integer("0"), Decimal("."), Fraction("000001")]}, + {value: 0.0000001, string: "0.0000001", parts: [Integer("0"), Decimal("."), Fraction("0000001")]}, + + {value: 12, string: "12", parts: [Integer("12")]}, + {value: 123, string: "123", parts: [Integer("123")]}, + {value: 1234, string: "1.2K", parts: [Integer("1"), Decimal("."), Fraction("2"), Compact("K")]}, + {value: 12345, string: "12K", parts: [Integer("12"), Compact("K")]}, + {value: 123456, string: "123K", parts: [Integer("123"), Compact("K")]}, + {value: 1234567, string: "1.2M", parts: [Integer("1"), Decimal("."), Fraction("2"), Compact("M")]}, + {value: 12345678, string: "12M", parts: [Integer("12"), Compact("M")]}, + {value: 123456789, string: "123M", parts: [Integer("123"), Compact("M")]}, + + {value: Infinity, string: "∞", parts: [Inf("∞")]}, + {value: -Infinity, string: "-∞", parts: [MinusSign("-"), Inf("∞")]}, + + {value: NaN, string: "NaN", parts: [Nan("NaN")]}, + {value: -NaN, string: "NaN", parts: [Nan("NaN")]}, + ], + }, + + // Compact symbol can consist of multiple characters, e.g. when it's an abbreviation. + { + locale: "de", + options: { + notation: "compact", + compactDisplay: "short", + }, + values: [ + {value: 1e6, string: "1\u00A0Mio.", parts: [Integer("1"), Literal("\u00A0"), Compact("Mio.")]}, + {value: 1e9, string: "1\u00A0Mrd.", parts: [Integer("1"), Literal("\u00A0"), Compact("Mrd.")]}, + {value: 1e12, string: "1\u00A0Bio.", parts: [Integer("1"), Literal("\u00A0"), Compact("Bio.")]}, + + // CLDR doesn't support "Billiarde" (Brd.), Trillion (Trill.), etc. + {value: 1e15, string: "1000\u00A0Bio.", parts: [Integer("1000"), Literal("\u00A0"), Compact("Bio.")]}, + ], + }, + + // Digits are grouped in myriads (every 10,000) in Chinese. + { + locale: "zh", + options: { + notation: "compact", + compactDisplay: "short", + }, + values: [ + {value: 1, string: "1", parts: [Integer("1")]}, + {value: 10, string: "10", parts: [Integer("10")]}, + {value: 100, string: "100", parts: [Integer("100")]}, + {value: 1000, string: "1000", parts: [Integer("1000")]}, + + {value: 10e3, string: "1\u4E07", parts: [Integer("1"), Compact("\u4E07")]}, + {value: 100e3, string: "10\u4E07", parts: [Integer("10"), Compact("\u4E07")]}, + {value: 1000e3, string: "100\u4E07", parts: [Integer("100"), Compact("\u4E07")]}, + {value: 10000e3, string: "1000\u4E07", parts: [Integer("1000"), Compact("\u4E07")]}, + + {value: 10e7, string: "1\u4EBF", parts: [Integer("1"), Compact("\u4EBF")]}, + {value: 100e7, string: "10\u4EBF", parts: [Integer("10"), Compact("\u4EBF")]}, + {value: 1000e7, string: "100\u4EBF", parts: [Integer("100"), Compact("\u4EBF")]}, + {value: 10000e7, string: "1000\u4EBF", parts: [Integer("1000"), Compact("\u4EBF")]}, + + {value: 10e11, string: "1\u4E07\u4EBF", parts: [Integer("1"), Compact("\u4E07\u4EBF")]}, + {value: 100e11, string: "10\u4E07\u4EBF", parts: [Integer("10"), Compact("\u4E07\u4EBF")]}, + {value: 1000e11, string: "100\u4E07\u4EBF", parts: [Integer("100"), Compact("\u4E07\u4EBF")]}, + {value: 10000e11, string: "1000\u4E07\u4EBF", parts: [Integer("1000"), Compact("\u4E07\u4EBF")]}, + + {value: 100000e11, string: "10,000\u4E07\u4EBF", parts: [Integer("10"), Group(","), Integer("000"), Compact("\u4E07\u4EBF")]}, + ], + }, +]; + +runNumberFormattingTestcases(testcases); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/notation-compact-with-fraction-digits.js b/js/src/tests/non262/Intl/NumberFormat/notation-compact-with-fraction-digits.js new file mode 100644 index 0000000000..4bdf26b9ad --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/notation-compact-with-fraction-digits.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +let nf = new Intl.NumberFormat("en", { + minimumFractionDigits: 0, + maximumFractionDigits: 2, + notation: "compact", +}); + +assertEq(nf.format(1500), "1.5K"); +assertEq(nf.format(1520), "1.52K"); +assertEq(nf.format(1540), "1.54K"); +assertEq(nf.format(1550), "1.55K"); +assertEq(nf.format(1560), "1.56K"); +assertEq(nf.format(1580), "1.58K"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/notation-engineering.js b/js/src/tests/non262/Intl/NumberFormat/notation-engineering.js new file mode 100644 index 0000000000..b4c0e19e53 --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/notation-engineering.js @@ -0,0 +1,136 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const { + Nan, Inf, Integer, MinusSign, PlusSign, Decimal, Fraction, Group, + ExponentSeparator, ExponentInteger, ExponentMinusSign, +} = NumberFormatParts; + +const testcases = [ + { + locale: "en", + options: { + notation: "engineering", + }, + values: [ + {value: +0, string: "0E0", parts: [Integer("0"), ExponentSeparator("E"), ExponentInteger("0")]}, + {value: -0, string: "-0E0", parts: [MinusSign("-"), Integer("0"), ExponentSeparator("E"), ExponentInteger("0")]}, + {value: 0n, string: "0E0", parts: [Integer("0"), ExponentSeparator("E"), ExponentInteger("0")]}, + + {value: 1, string: "1E0", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("0")]}, + {value: 10, string: "10E0", parts: [Integer("10"), ExponentSeparator("E"), ExponentInteger("0")]}, + {value: 100, string: "100E0", parts: [Integer("100"), ExponentSeparator("E"), ExponentInteger("0")]}, + {value: 1000, string: "1E3", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("3")]}, + {value: 10000, string: "10E3", parts: [Integer("10"), ExponentSeparator("E"), ExponentInteger("3")]}, + {value: 100000, string: "100E3", parts: [Integer("100"), ExponentSeparator("E"), ExponentInteger("3")]}, + {value: 1000000, string: "1E6", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("6")]}, + + {value: 1n, string: "1E0", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("0")]}, + {value: 10n, string: "10E0", parts: [Integer("10"), ExponentSeparator("E"), ExponentInteger("0")]}, + {value: 100n, string: "100E0", parts: [Integer("100"), ExponentSeparator("E"), ExponentInteger("0")]}, + {value: 1000n, string: "1E3", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("3")]}, + {value: 10000n, string: "10E3", parts: [Integer("10"), ExponentSeparator("E"), ExponentInteger("3")]}, + {value: 100000n, string: "100E3", parts: [Integer("100"), ExponentSeparator("E"), ExponentInteger("3")]}, + {value: 1000000n, string: "1E6", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("6")]}, + + {value: 0.1, string: "100E-3", parts: [Integer("100"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("3")]}, + {value: 0.01, string: "10E-3", parts: [Integer("10"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("3")]}, + {value: 0.001, string: "1E-3", parts: [Integer("1"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("3")]}, + {value: 0.0001, string: "100E-6", parts: [Integer("100"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("6")]}, + {value: 0.00001, string: "10E-6", parts: [Integer("10"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("6")]}, + {value: 0.000001, string: "1E-6", parts: [Integer("1"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("6")]}, + {value: 0.0000001, string: "100E-9", parts: [Integer("100"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("9")]}, + + {value: Infinity, string: "∞", parts: [Inf("∞")]}, + {value: -Infinity, string: "-∞", parts: [MinusSign("-"), Inf("∞")]}, + + {value: NaN, string: "NaN", parts: [Nan("NaN")]}, + {value: -NaN, string: "NaN", parts: [Nan("NaN")]}, + ], + }, + + // Exponent modifications take place early, so while in the "standard" notation + // `Intl.NumberFormat("en", {maximumFractionDigits: 0}).format(0.1)` returns "0", for + // "engineering" notation the result string is not "0", but instead "100E-3". + + { + locale: "en", + options: { + notation: "engineering", + maximumFractionDigits: 0, + }, + values: [ + {value: 0.1, string: "100E-3", parts: [ + Integer("100"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("3") + ]}, + ], + }, + + { + locale: "en", + options: { + notation: "engineering", + minimumFractionDigits: 4, + }, + values: [ + {value: 10, string: "10.0000E0", parts: [ + Integer("10"), Decimal("."), Fraction("0000"), ExponentSeparator("E"), ExponentInteger("0") + ]}, + {value: 0.1, string: "100.0000E-3", parts: [ + Integer("100"), Decimal("."), Fraction("0000"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("3") + ]}, + ], + }, + + { + locale: "en", + options: { + notation: "engineering", + minimumIntegerDigits: 4, + }, + values: [ + {value: 10, string: "0,010E0", parts: [ + Integer("0"), Group(","), Integer("010"), ExponentSeparator("E"), ExponentInteger("0") + ]}, + {value: 0.1, string: "0,100E-3", parts: [ + Integer("0"), Group(","), Integer("100"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("3") + ]}, + ], + }, + + { + locale: "en", + options: { + notation: "engineering", + minimumSignificantDigits: 4, + }, + values: [ + {value: 10, string: "10.00E0", parts: [ + Integer("10"), Decimal("."), Fraction("00"), ExponentSeparator("E"), ExponentInteger("0") + ]}, + {value: 0.1, string: "100.0E-3", parts: [ + Integer("100"), Decimal("."), Fraction("0"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("3") + ]}, + ], + }, + + { + locale: "en", + options: { + notation: "engineering", + maximumSignificantDigits: 1, + }, + values: [ + {value: 12, string: "10E0", parts: [ + Integer("10"), ExponentSeparator("E"), ExponentInteger("0") + ]}, + {value: 0.12, string: "100E-3", parts: [ + Integer("100"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("3") + ]}, + ], + }, +]; + +runNumberFormattingTestcases(testcases); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/notation-scientific.js b/js/src/tests/non262/Intl/NumberFormat/notation-scientific.js new file mode 100644 index 0000000000..f14a660129 --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/notation-scientific.js @@ -0,0 +1,136 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const { + Nan, Inf, Integer, MinusSign, PlusSign, Decimal, Fraction, Group, + ExponentSeparator, ExponentInteger, ExponentMinusSign, +} = NumberFormatParts; + +const testcases = [ + { + locale: "en", + options: { + notation: "scientific", + }, + values: [ + {value: +0, string: "0E0", parts: [Integer("0"), ExponentSeparator("E"), ExponentInteger("0")]}, + {value: -0, string: "-0E0", parts: [MinusSign("-"), Integer("0"), ExponentSeparator("E"), ExponentInteger("0")]}, + {value: 0n, string: "0E0", parts: [Integer("0"), ExponentSeparator("E"), ExponentInteger("0")]}, + + {value: 1, string: "1E0", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("0")]}, + {value: 10, string: "1E1", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("1")]}, + {value: 100, string: "1E2", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("2")]}, + {value: 1000, string: "1E3", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("3")]}, + {value: 10000, string: "1E4", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("4")]}, + {value: 100000, string: "1E5", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("5")]}, + {value: 1000000, string: "1E6", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("6")]}, + + {value: 1n, string: "1E0", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("0")]}, + {value: 10n, string: "1E1", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("1")]}, + {value: 100n, string: "1E2", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("2")]}, + {value: 1000n, string: "1E3", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("3")]}, + {value: 10000n, string: "1E4", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("4")]}, + {value: 100000n, string: "1E5", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("5")]}, + {value: 1000000n, string: "1E6", parts: [Integer("1"), ExponentSeparator("E"), ExponentInteger("6")]}, + + {value: 0.1, string: "1E-1", parts: [Integer("1"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("1")]}, + {value: 0.01, string: "1E-2", parts: [Integer("1"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("2")]}, + {value: 0.001, string: "1E-3", parts: [Integer("1"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("3")]}, + {value: 0.0001, string: "1E-4", parts: [Integer("1"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("4")]}, + {value: 0.00001, string: "1E-5", parts: [Integer("1"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("5")]}, + {value: 0.000001, string: "1E-6", parts: [Integer("1"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("6")]}, + {value: 0.0000001, string: "1E-7", parts: [Integer("1"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("7")]}, + + {value: Infinity, string: "∞", parts: [Inf("∞")]}, + {value: -Infinity, string: "-∞", parts: [MinusSign("-"), Inf("∞")]}, + + {value: NaN, string: "NaN", parts: [Nan("NaN")]}, + {value: -NaN, string: "NaN", parts: [Nan("NaN")]}, + ], + }, + + // Exponent modifications take place early, so while in the "standard" notation + // `Intl.NumberFormat("en", {maximumFractionDigits: 0}).format(0.1)` returns "0", for + // "scientific" notation the result string is not "0", but instead "1E-1". + + { + locale: "en", + options: { + notation: "scientific", + maximumFractionDigits: 0, + }, + values: [ + {value: 0.1, string: "1E-1", parts: [ + Integer("1"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("1") + ]}, + ], + }, + + { + locale: "en", + options: { + notation: "scientific", + minimumFractionDigits: 4, + }, + values: [ + {value: 10, string: "1.0000E1", parts: [ + Integer("1"), Decimal("."), Fraction("0000"), ExponentSeparator("E"), ExponentInteger("1") + ]}, + {value: 0.1, string: "1.0000E-1", parts: [ + Integer("1"), Decimal("."), Fraction("0000"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("1") + ]}, + ], + }, + + { + locale: "en", + options: { + notation: "scientific", + minimumIntegerDigits: 4, + }, + values: [ + {value: 10, string: "0,001E1", parts: [ + Integer("0"), Group(","), Integer("001"), ExponentSeparator("E"), ExponentInteger("1") + ]}, + {value: 0.1, string: "0,001E-1", parts: [ + Integer("0"), Group(","), Integer("001"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("1") + ]}, + ], + }, + + { + locale: "en", + options: { + notation: "scientific", + minimumSignificantDigits: 4, + }, + values: [ + {value: 10, string: "1.000E1", parts: [ + Integer("1"), Decimal("."), Fraction("000"), ExponentSeparator("E"), ExponentInteger("1") + ]}, + {value: 0.1, string: "1.000E-1", parts: [ + Integer("1"), Decimal("."), Fraction("000"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("1") + ]}, + ], + }, + + { + locale: "en", + options: { + notation: "scientific", + maximumSignificantDigits: 1, + }, + values: [ + {value: 12, string: "1E1", parts: [ + Integer("1"), ExponentSeparator("E"), ExponentInteger("1") + ]}, + {value: 0.12, string: "1E-1", parts: [ + Integer("1"), ExponentSeparator("E"), ExponentMinusSign("-"), ExponentInteger("1") + ]}, + ], + }, +]; + +runNumberFormattingTestcases(testcases); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/numberingSystem-format.js b/js/src/tests/non262/Intl/NumberFormat/numberingSystem-format.js new file mode 100644 index 0000000000..c0b9ba78ed --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/numberingSystem-format.js @@ -0,0 +1,18 @@ +for (let [numberingSystem, {digits, algorithmic}] of Object.entries(numberingSystems)) { + if (algorithmic) { + // We don't yet support algorithmic numbering systems. + continue; + } + + let nf = new Intl.NumberFormat("en", {numberingSystem}); + + assertEq([...digits].length, 10, "expect exactly ten digits for each numbering system"); + + let i = 0; + for (let digit of digits) { + assertEq(nf.format(i++), digit); + } +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/numberingSystem-option.js b/js/src/tests/non262/Intl/NumberFormat/numberingSystem-option.js new file mode 100644 index 0000000000..4624ee5192 --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/numberingSystem-option.js @@ -0,0 +1,60 @@ +const defaultLocale = "en"; +const defaultNumberingSystem = new Intl.NumberFormat(defaultLocale).resolvedOptions().numberingSystem; + +function createWithLocale(locale, numberingSystem) { + return new Intl.NumberFormat(locale, {numberingSystem}); +} + +function create(numberingSystem) { + return createWithLocale(defaultLocale, numberingSystem); +} + +// Empty string should throw. +assertThrowsInstanceOf(() => create(""), RangeError); + +// Trailing \0 should throw. +assertThrowsInstanceOf(() => create("latn\0"), RangeError); + +// Too short or too long strings should throw. +assertThrowsInstanceOf(() => create("a"), RangeError); +assertThrowsInstanceOf(() => create("toolongstring"), RangeError); + +// Throw even when prefix is valid. +assertThrowsInstanceOf(() => create("latn-toolongstring"), RangeError); + +// |numberingSystem| can be set to |undefined|. +let nf = create(undefined); +assertEq(nf.resolvedOptions().numberingSystem, defaultNumberingSystem); + +// Unsupported numbering systems are ignored. +nf = create("xxxxxxxx"); +assertEq(nf.resolvedOptions().numberingSystem, defaultNumberingSystem); + +// Numbering system in options overwrite Unicode extension keyword. +nf = createWithLocale(`${defaultLocale}-u-nu-thai`, "arab"); +assertEq(nf.resolvedOptions().locale, defaultLocale); +assertEq(nf.resolvedOptions().numberingSystem, "arab"); + +// |numberingSystem| option ignores case. +nf = create("ARAB"); +assertEq(nf.resolvedOptions().locale, defaultLocale); +assertEq(nf.resolvedOptions().numberingSystem, "arab"); + +for (let [numberingSystem, {algorithmic}] of Object.entries(numberingSystems)) { + let nf1 = new Intl.NumberFormat(`${defaultLocale}-u-nu-${numberingSystem}`); + let nf2 = new Intl.NumberFormat(defaultLocale, {numberingSystem}); + + if (!algorithmic) { + assertEq(nf1.resolvedOptions().numberingSystem, numberingSystem); + assertEq(nf2.resolvedOptions().numberingSystem, numberingSystem); + } else { + // We don't yet support algorithmic numbering systems. + assertEq(nf1.resolvedOptions().numberingSystem, defaultNumberingSystem); + assertEq(nf2.resolvedOptions().numberingSystem, defaultNumberingSystem); + } + + assertEq(nf2.format(0), nf1.format(0)); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/options-emulate-undefined.js b/js/src/tests/non262/Intl/NumberFormat/options-emulate-undefined.js new file mode 100644 index 0000000000..ddb2d61350 --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/options-emulate-undefined.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// createIsHTMLDDA is only available when running tests in the shell, +// not the browser +if (typeof createIsHTMLDDA === "function") { + let nf = new Intl.NumberFormat('en-US', createIsHTMLDDA()); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/remove-unicode-extensions.js b/js/src/tests/non262/Intl/NumberFormat/remove-unicode-extensions.js new file mode 100644 index 0000000000..87cfc317cb --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/remove-unicode-extensions.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Locale processing is supposed to internally remove any Unicode extension +// sequences in the locale. Test that various weird testcases invoking +// algorithmic edge cases don't assert or throw exceptions. + +var weirdCases = + [ + "en-x-u-foo", + "en-a-bar-x-u-foo", + "en-x-u-foo-a-bar", + "en-a-bar-u-baz-x-u-foo", + ]; + +for (var locale of weirdCases) + Intl.NumberFormat(locale).format(5); + +assertThrowsInstanceOf(() => Intl.NumberFormat("x-u-foo"), RangeError); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/rounding-increment.js b/js/src/tests/non262/Intl/NumberFormat/rounding-increment.js new file mode 100644 index 0000000000..69c457a04a --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/rounding-increment.js @@ -0,0 +1,115 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Nickel rounding. +{ + let nf = new Intl.NumberFormat("en", { + minimumFractionDigits: 2, + maximumFractionDigits: 2, + roundingIncrement: 5, + }); + + assertEq(nf.format(1.22), "1.20"); + assertEq(nf.format(1.224), "1.20"); + assertEq(nf.format(1.225), "1.25"); + assertEq(nf.format(1.23), "1.25"); +} + +// Dime rounding. +{ + let nf = new Intl.NumberFormat("en", { + minimumFractionDigits: 2, + maximumFractionDigits: 2, + roundingIncrement: 10, + }); + + assertEq(nf.format(1.24), "1.20"); + assertEq(nf.format(1.249), "1.20"); + assertEq(nf.format(1.250), "1.30"); + assertEq(nf.format(1.25), "1.30"); +} + +// Rounding increment option is rounded down. +{ + let nf1 = new Intl.NumberFormat("en", { + minimumFractionDigits: 0, + maximumFractionDigits: 0, + roundingIncrement: 10, + }); + + let nf2 = new Intl.NumberFormat("en", { + minimumFractionDigits: 0, + maximumFractionDigits: 0, + roundingIncrement: 10.1, + }); + + let nf3 = new Intl.NumberFormat("en", { + minimumFractionDigits: 0, + maximumFractionDigits: 0, + roundingIncrement: 10.9, + }); + + assertEq(nf1.resolvedOptions().roundingIncrement, 10); + assertEq(nf2.resolvedOptions().roundingIncrement, 10); + assertEq(nf3.resolvedOptions().roundingIncrement, 10); + + assertEq(nf1.format(123), "120"); + assertEq(nf2.format(123), "120"); + assertEq(nf3.format(123), "120"); +} + +// |minimumFractionDigits| must be equal to |maximumFractionDigits| when +// |roundingIncrement| is used. +// +// |minimumFractionDigits| defaults to zero. +{ + let nf = new Intl.NumberFormat("en", { + roundingIncrement: 10, + // minimumFractionDigits: 0, (default) + maximumFractionDigits: 0, + }); + + let resolved = nf.resolvedOptions(); + assertEq(resolved.minimumFractionDigits, 0); + assertEq(resolved.maximumFractionDigits, 0); + assertEq(resolved.roundingIncrement, 10); + + assertEq(nf.format(123), "120"); + assertEq(nf.format(123.456), "120"); +} + +// |maximumFractionDigitsDefault| is set to |minimumFractionDigitsDefault| when +// roundingIncrement isn't equal to 1. +{ + let options = { + roundingIncrement: 10, + // minimumFractionDigits: 0, (default) + // maximumFractionDigits: 0, (default) + }; + let nf = new Intl.NumberFormat("en", options); + assertEq(nf.resolvedOptions().minimumFractionDigits, 0); + assertEq(nf.resolvedOptions().maximumFractionDigits, 0); +} + +// |maximumFractionDigits| must be equal to |minimumFractionDigits| when +// roundingIncrement isn't equal to 1. +{ + let options = { + roundingIncrement: 10, + // minimumFractionDigits: 0, (default) + maximumFractionDigits: 1, + }; + assertThrowsInstanceOf(() => new Intl.NumberFormat("en", options), RangeError); +} + +// Invalid values. +for (let roundingIncrement of [-1, 0, Infinity, NaN]){ + let options = { + roundingIncrement, + minimumFractionDigits: 0, + maximumFractionDigits: 0, + }; + assertThrowsInstanceOf(() => new Intl.NumberFormat("en", options), RangeError); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/rounding-mode.js b/js/src/tests/non262/Intl/NumberFormat/rounding-mode.js new file mode 100644 index 0000000000..b58a7ad3da --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/rounding-mode.js @@ -0,0 +1,287 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const tests = [ + // Special values: Zeros and non-finite values. + { + value: 0, + options: {}, + roundingModes: { + ceil: "0", + floor: "0", + expand: "0", + trunc: "0", + halfCeil: "0", + halfFloor: "0", + halfExpand: "0", + halfTrunc: "0", + halfEven: "0", + }, + }, + { + value: -0, + options: {}, + roundingModes: { + ceil: "-0", + floor: "-0", + expand: "-0", + trunc: "-0", + halfCeil: "-0", + halfFloor: "-0", + halfExpand: "-0", + halfTrunc: "-0", + halfEven: "-0", + }, + }, + { + value: -Infinity, + options: {}, + roundingModes: { + ceil: "-∞", + floor: "-∞", + expand: "-∞", + trunc: "-∞", + halfCeil: "-∞", + halfFloor: "-∞", + halfExpand: "-∞", + halfTrunc: "-∞", + halfEven: "-∞", + }, + }, + { + value: Infinity, + options: {}, + roundingModes: { + ceil: "∞", + floor: "∞", + expand: "∞", + trunc: "∞", + halfCeil: "∞", + halfFloor: "∞", + halfExpand: "∞", + halfTrunc: "∞", + halfEven: "∞", + }, + }, + { + value: NaN, + options: {}, + roundingModes: { + ceil: "NaN", + floor: "NaN", + expand: "NaN", + trunc: "NaN", + halfCeil: "NaN", + halfFloor: "NaN", + halfExpand: "NaN", + halfTrunc: "NaN", + halfEven: "NaN", + }, + }, + + // Integer rounding with positive values. + { + value: 0.4, + options: {maximumFractionDigits: 0}, + roundingModes: { + ceil: "1", + floor: "0", + expand: "1", + trunc: "0", + halfCeil: "0", + halfFloor: "0", + halfExpand: "0", + halfTrunc: "0", + halfEven: "0", + }, + }, + { + value: 0.5, + options: {maximumFractionDigits: 0}, + roundingModes: { + ceil: "1", + floor: "0", + expand: "1", + trunc: "0", + halfCeil: "1", + halfFloor: "0", + halfExpand: "1", + halfTrunc: "0", + halfEven: "0", + }, + }, + { + value: 0.6, + options: {maximumFractionDigits: 0}, + roundingModes: { + ceil: "1", + floor: "0", + expand: "1", + trunc: "0", + halfCeil: "1", + halfFloor: "1", + halfExpand: "1", + halfTrunc: "1", + halfEven: "1", + }, + }, + + // Integer rounding with negative values. + { + value: -0.4, + options: {maximumFractionDigits: 0}, + roundingModes: { + ceil: "-0", + floor: "-1", + expand: "-1", + trunc: "-0", + halfCeil: "-0", + halfFloor: "-0", + halfExpand: "-0", + halfTrunc: "-0", + halfEven: "-0", + }, + }, + { + value: -0.5, + options: {maximumFractionDigits: 0}, + roundingModes: { + ceil: "-0", + floor: "-1", + expand: "-1", + trunc: "-0", + halfCeil: "-0", + halfFloor: "-1", + halfExpand: "-1", + halfTrunc: "-0", + halfEven: "-0", + }, + }, + { + value: -0.6, + options: {maximumFractionDigits: 0}, + roundingModes: { + ceil: "-0", + floor: "-1", + expand: "-1", + trunc: "-0", + halfCeil: "-1", + halfFloor: "-1", + halfExpand: "-1", + halfTrunc: "-1", + halfEven: "-1", + }, + }, + + // Fractional digits rounding with positive values. + { + value: 0.04, + options: {maximumFractionDigits: 1}, + roundingModes: { + ceil: "0.1", + floor: "0", + expand: "0.1", + trunc: "0", + halfCeil: "0", + halfFloor: "0", + halfExpand: "0", + halfTrunc: "0", + halfEven: "0", + }, + }, + { + value: 0.05, + options: {maximumFractionDigits: 1}, + roundingModes: { + ceil: "0.1", + floor: "0", + expand: "0.1", + trunc: "0", + halfCeil: "0.1", + halfFloor: "0", + halfExpand: "0.1", + halfTrunc: "0", + halfEven: "0", + }, + }, + { + value: 0.06, + options: {maximumFractionDigits: 1}, + roundingModes: { + ceil: "0.1", + floor: "0", + expand: "0.1", + trunc: "0", + halfCeil: "0.1", + halfFloor: "0.1", + halfExpand: "0.1", + halfTrunc: "0.1", + halfEven: "0.1", + }, + }, + + // Fractional digits rounding with negative values. + { + value: -0.04, + options: {maximumFractionDigits: 1}, + roundingModes: { + ceil: "-0", + floor: "-0.1", + expand: "-0.1", + trunc: "-0", + halfCeil: "-0", + halfFloor: "-0", + halfExpand: "-0", + halfTrunc: "-0", + halfEven: "-0", + }, + }, + { + value: -0.05, + options: {maximumFractionDigits: 1}, + roundingModes: { + ceil: "-0", + floor: "-0.1", + expand: "-0.1", + trunc: "-0", + halfCeil: "-0", + halfFloor: "-0.1", + halfExpand: "-0.1", + halfTrunc: "-0", + halfEven: "-0", + }, + }, + { + value: -0.06, + options: {maximumFractionDigits: 1}, + roundingModes: { + ceil: "-0", + floor: "-0.1", + expand: "-0.1", + trunc: "-0", + halfCeil: "-0.1", + halfFloor: "-0.1", + halfExpand: "-0.1", + halfTrunc: "-0.1", + halfEven: "-0.1", + }, + }, +]; + +for (let {value, options, roundingModes} of tests) { + for (let [roundingMode, expected] of Object.entries(roundingModes)) { + let nf = new Intl.NumberFormat("en", {...options, roundingMode}); + assertEq(nf.format(value), expected, `value=${value}, roundingMode=${roundingMode}`); + assertEq(nf.resolvedOptions().roundingMode, roundingMode); + } +} + +// Default value is "halfExpand". +assertEq(new Intl.NumberFormat().resolvedOptions().roundingMode, "halfExpand"); + +// Invalid values. +for (let roundingMode of ["", null, "halfOdd", "halfUp", "Up", "up"]){ + assertThrowsInstanceOf(() => new Intl.NumberFormat("en", {roundingMode}), RangeError); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/rounding-priority.js b/js/src/tests/non262/Intl/NumberFormat/rounding-priority.js new file mode 100644 index 0000000000..2e672a3022 --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/rounding-priority.js @@ -0,0 +1,132 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const tests = [ + // Rounding conflict with maximum fraction/significand digits. + { + value: 4.321, + options: { + maximumFractionDigits: 2, + maximumSignificantDigits: 2, + }, + roundingPriorities: { + auto: "4.3", + lessPrecision: "4.3", + morePrecision: "4.32", + }, + }, + { + value: 4.321, + options: { + maximumFractionDigits: 2, + minimumFractionDigits: 2, + maximumSignificantDigits: 2, + }, + roundingPriorities: { + auto: "4.3", + lessPrecision: "4.3", + morePrecision: "4.32", + }, + }, + { + value: 4.321, + options: { + maximumFractionDigits: 2, + maximumSignificantDigits: 2, + minimumSignificantDigits: 2, + }, + roundingPriorities: { + auto: "4.3", + lessPrecision: "4.3", + morePrecision: "4.32", + }, + }, + { + value: 4.321, + options: { + maximumFractionDigits: 2, + minimumFractionDigits: 2, + maximumSignificantDigits: 2, + minimumSignificantDigits: 2, + }, + roundingPriorities: { + auto: "4.3", + lessPrecision: "4.3", + morePrecision: "4.32", + }, + }, + + // Rounding conflict with minimum fraction/significand digits. + { + value: 1.0, + options: { + minimumFractionDigits: 2, + minimumSignificantDigits: 2, + }, + roundingPriorities: { + auto: "1.0", + // Returning "1.00" for both options seems unexpected. Also filed at + // . + lessPrecision: "1.00", + morePrecision: "1.0", + }, + }, + { + value: 1.0, + options: { + minimumFractionDigits: 2, + maximumFractionDigits: 2, + minimumSignificantDigits: 2, + }, + roundingPriorities: { + auto: "1.0", + lessPrecision: "1.00", + morePrecision: "1.0", + }, + }, + { + value: 1.0, + options: { + minimumFractionDigits: 2, + minimumSignificantDigits: 2, + maximumSignificantDigits: 2, + }, + roundingPriorities: { + auto: "1.0", + lessPrecision: "1.0", + morePrecision: "1.00", + }, + }, + { + value: 1.0, + options: { + minimumFractionDigits: 2, + maximumFractionDigits: 2, + minimumSignificantDigits: 2, + maximumSignificantDigits: 2, + }, + roundingPriorities: { + auto: "1.0", + lessPrecision: "1.0", + morePrecision: "1.00", + }, + }, +]; + +for (let {value, options, roundingPriorities} of tests) { + for (let [roundingPriority, expected] of Object.entries(roundingPriorities)) { + let nf = new Intl.NumberFormat("en", {...options, roundingPriority}); + assertEq(nf.resolvedOptions().roundingPriority, roundingPriority); + assertEq(nf.format(value), expected, `value=${value}, roundingPriority=${roundingPriority}`); + } +} + +// Default value of "auto". +assertEq(new Intl.NumberFormat().resolvedOptions().roundingPriority, "auto"); + +// Invalid values. +for (let roundingPriority of ["", null, "more", "less", "never"]){ + assertThrowsInstanceOf(() => new Intl.NumberFormat("en", {roundingPriority}), RangeError); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/shell.js b/js/src/tests/non262/Intl/NumberFormat/shell.js new file mode 100644 index 0000000000..471fdad71b --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/shell.js @@ -0,0 +1,77 @@ +function GenericPartCreator(type) { + return str => ({ type, value: str }); +} + +const NumberFormatParts = { + Nan: GenericPartCreator("nan"), + Inf: GenericPartCreator("infinity"), + Integer: GenericPartCreator("integer"), + Group: GenericPartCreator("group"), + Decimal: GenericPartCreator("decimal"), + Fraction: GenericPartCreator("fraction"), + MinusSign: GenericPartCreator("minusSign"), + PlusSign: GenericPartCreator("plusSign"), + PercentSign: GenericPartCreator("percentSign"), + Currency: GenericPartCreator("currency"), + Literal: GenericPartCreator("literal"), + ExponentSeparator: GenericPartCreator("exponentSeparator"), + ExponentMinusSign: GenericPartCreator("exponentMinusSign"), + ExponentInteger: GenericPartCreator("exponentInteger"), + Compact: GenericPartCreator("compact"), + Unit: GenericPartCreator("unit"), +}; + +function NumberRangeFormatParts(source) { + let entries = Object.entries(NumberFormatParts) + + entries.push(["Approx", GenericPartCreator("approximatelySign")]); + + return Object.fromEntries(entries.map(([key, part]) => { + let partWithSource = str => { + return Object.defineProperty(part(str), "source", { + value: source, writable: true, enumerable: true, configurable: true + }); + }; + return [key, partWithSource]; + })); +} + +function assertParts(nf, x, expected) { + var parts = nf.formatToParts(x); + assertEq(parts.map(part => part.value).join(""), nf.format(x), + "formatToParts and format must agree"); + + var len = parts.length; + assertEq(len, expected.length, "parts count mismatch"); + for (var i = 0; i < len; i++) { + assertEq(parts[i].type, expected[i].type, "type mismatch at " + i); + assertEq(parts[i].value, expected[i].value, "value mismatch at " + i); + } +} + +function assertRangeParts(nf, start, end, expected) { + var parts = nf.formatRangeToParts(start, end); + assertEq(parts.map(part => part.value).join(""), nf.formatRange(start, end), + "formatRangeToParts and formatRange must agree"); + + var len = parts.length; + assertEq(len, expected.length, "parts count mismatch"); + for (var i = 0; i < len; i++) { + assertEq(parts[i].type, expected[i].type, "type mismatch at " + i); + assertEq(parts[i].value, expected[i].value, "value mismatch at " + i); + assertEq(parts[i].source, expected[i].source, "source mismatch at " + i); + } +} + +function runNumberFormattingTestcases(testcases) { + for (let {locale, options, values} of testcases) { + let nf = new Intl.NumberFormat(locale, options); + + for (let {value, string, parts} of values) { + assertEq(nf.format(value), string, + `locale=${locale}, options=${JSON.stringify(options)}, value=${value}`); + + assertParts(nf, value, parts); + } + } +} diff --git a/js/src/tests/non262/Intl/NumberFormat/sign-display.js b/js/src/tests/non262/Intl/NumberFormat/sign-display.js new file mode 100644 index 0000000000..b18517d847 --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/sign-display.js @@ -0,0 +1,187 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const { + Nan, Inf, Integer, MinusSign, PlusSign, Decimal, Fraction +} = NumberFormatParts; + +const testcases = [ + // "auto": Show the sign on negative numbers only. + { + locale: "en", + options: { + signDisplay: "auto", + }, + values: [ + {value: +0, string: "0", parts: [Integer("0")]}, + {value: -0, string: "-0", parts: [MinusSign("-"), Integer("0")]}, + {value: 0n, string: "0", parts: [Integer("0")]}, + + {value: 1, string: "1", parts: [Integer("1")]}, + {value: -1, string: "-1", parts: [MinusSign("-"), Integer("1")]}, + {value: 1n, string: "1", parts: [Integer("1")]}, + {value: -1n, string: "-1", parts: [MinusSign("-"), Integer("1")]}, + + {value: 0.1, string: "0.1", parts: [Integer("0"), Decimal("."), Fraction("1")]}, + {value: -0.1, string: "-0.1", parts: [MinusSign("-"), Integer("0"), Decimal("."), Fraction("1")]}, + + {value: 0.9, string: "0.9", parts: [Integer("0"), Decimal("."), Fraction("9")]}, + {value: -0.9, string: "-0.9", parts: [MinusSign("-"), Integer("0"), Decimal("."), Fraction("9")]}, + + {value: Infinity, string: "∞", parts: [Inf("∞")]}, + {value: -Infinity, string: "-∞", parts: [MinusSign("-"), Inf("∞")]}, + + {value: NaN, string: "NaN", parts: [Nan("NaN")]}, + {value: -NaN, string: "NaN", parts: [Nan("NaN")]}, + ], + }, + + // "never": Show the sign on neither positive nor negative numbers. + { + locale: "en", + options: { + signDisplay: "never", + }, + values: [ + {value: +0, string: "0", parts: [Integer("0")]}, + {value: -0, string: "0", parts: [Integer("0")]}, + {value: 0n, string: "0", parts: [Integer("0")]}, + + {value: 1, string: "1", parts: [Integer("1")]}, + {value: -1, string: "1", parts: [Integer("1")]}, + {value: 1n, string: "1", parts: [Integer("1")]}, + {value: -1n, string: "1", parts: [Integer("1")]}, + + {value: 0.1, string: "0.1", parts: [Integer("0"), Decimal("."), Fraction("1")]}, + {value: -0.1, string: "0.1", parts: [Integer("0"), Decimal("."), Fraction("1")]}, + + {value: 0.9, string: "0.9", parts: [Integer("0"), Decimal("."), Fraction("9")]}, + {value: -0.9, string: "0.9", parts: [Integer("0"), Decimal("."), Fraction("9")]}, + + {value: Infinity, string: "∞", parts: [Inf("∞")]}, + {value: -Infinity, string: "∞", parts: [Inf("∞")]}, + + {value: NaN, string: "NaN", parts: [Nan("NaN")]}, + {value: -NaN, string: "NaN", parts: [Nan("NaN")]}, + ], + }, + + // "always": Show the sign on positive and negative numbers including zero. + { + locale: "en", + options: { + signDisplay: "always", + }, + values: [ + {value: +0, string: "+0", parts: [PlusSign("+"), Integer("0")]}, + {value: -0, string: "-0", parts: [MinusSign("-"), Integer("0")]}, + {value: 0n, string: "+0", parts: [PlusSign("+"), Integer("0")]}, + + {value: 1, string: "+1", parts: [PlusSign("+"), Integer("1")]}, + {value: -1, string: "-1", parts: [MinusSign("-"), Integer("1")]}, + {value: 1n, string: "+1", parts: [PlusSign("+"), Integer("1")]}, + {value: -1n, string: "-1", parts: [MinusSign("-"), Integer("1")]}, + + {value: 0.1, string: "+0.1", parts: [PlusSign("+"), Integer("0"), Decimal("."), Fraction("1")]}, + {value: -0.1, string: "-0.1", parts: [MinusSign("-"), Integer("0"), Decimal("."), Fraction("1")]}, + + {value: 0.9, string: "+0.9", parts: [PlusSign("+"), Integer("0"), Decimal("."), Fraction("9")]}, + {value: -0.9, string: "-0.9", parts: [MinusSign("-"), Integer("0"), Decimal("."), Fraction("9")]}, + + {value: Infinity, string: "+∞", parts: [PlusSign("+"), Inf("∞")]}, + {value: -Infinity, string: "-∞", parts: [MinusSign("-"), Inf("∞")]}, + + {value: NaN, string: "+NaN", parts: [PlusSign("+"), Nan("NaN")]}, + {value: -NaN, string: "+NaN", parts: [PlusSign("+"), Nan("NaN")]}, + ], + }, + + // "exceptZero": Show the sign on positive and negative numbers but not zero. + { + locale: "en", + options: { + signDisplay: "exceptZero", + }, + values: [ + {value: +0, string: "0", parts: [Integer("0")]}, + {value: -0, string: "0", parts: [Integer("0")]}, + {value: 0n, string: "0", parts: [Integer("0")]}, + + {value: 1, string: "+1", parts: [PlusSign("+"), Integer("1")]}, + {value: -1, string: "-1", parts: [MinusSign("-"), Integer("1")]}, + {value: 1n, string: "+1", parts: [PlusSign("+"), Integer("1")]}, + {value: -1n, string: "-1", parts: [MinusSign("-"), Integer("1")]}, + + {value: 0.1, string: "+0.1", parts: [PlusSign("+"), Integer("0"), Decimal("."), Fraction("1")]}, + {value: -0.1, string: "-0.1", parts: [MinusSign("-"), Integer("0"), Decimal("."), Fraction("1")]}, + + {value: 0.9, string: "+0.9", parts: [PlusSign("+"), Integer("0"), Decimal("."), Fraction("9")]}, + {value: -0.9, string: "-0.9", parts: [MinusSign("-"), Integer("0"), Decimal("."), Fraction("9")]}, + + {value: Infinity, string: "+∞", parts: [PlusSign("+"), Inf("∞")]}, + {value: -Infinity, string: "-∞", parts: [MinusSign("-"), Inf("∞")]}, + + {value: NaN, string: "NaN", parts: [Nan("NaN")]}, + {value: -NaN, string: "NaN", parts: [Nan("NaN")]}, + ], + }, + + // Tests with suppressed fractional digits. + + // "auto": Show the sign on negative numbers only. + { + locale: "en", + options: { + signDisplay: "auto", + maximumFractionDigits: 0, + }, + values: [ + {value: +0.1, string: "0", parts: [Integer("0")]}, + {value: -0.1, string: "-0", parts: [MinusSign("-"), Integer("0")]}, + ], + }, + + // "never": Show the sign on neither positive nor negative numbers. + { + locale: "en", + options: { + signDisplay: "never", + maximumFractionDigits: 0, + }, + values: [ + {value: +0.1, string: "0", parts: [Integer("0")]}, + {value: -0.1, string: "0", parts: [Integer("0")]}, + ], + }, + + // "always": Show the sign on positive and negative numbers including zero. + { + locale: "en", + options: { + signDisplay: "always", + maximumFractionDigits: 0, + }, + values: [ + {value: +0.1, string: "+0", parts: [PlusSign("+"), Integer("0")]}, + {value: -0.1, string: "-0", parts: [MinusSign("-"), Integer("0")]}, + ], + }, + + // "exceptZero": Show the sign on positive and negative numbers but not zero. + { + locale: "en", + options: { + signDisplay: "exceptZero", + maximumFractionDigits: 0, + }, + + values: [ + {value: +0.1, string: "0", parts: [Integer("0")]}, + {value: -0.1, string: "0", parts: [Integer("0")]}, + ], + } +]; + +runNumberFormattingTestcases(testcases); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/significantDigitsOfZero.js b/js/src/tests/non262/Intl/NumberFormat/significantDigitsOfZero.js new file mode 100644 index 0000000000..c569313266 --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/significantDigitsOfZero.js @@ -0,0 +1,38 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) +// -- test that NumberFormat correctly formats 0 with various numbers of significant digits + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var testData = [ + {minimumSignificantDigits: 1, maximumSignificantDigits: 1, expected: "0"}, + {minimumSignificantDigits: 1, maximumSignificantDigits: 2, expected: "0"}, + {minimumSignificantDigits: 1, maximumSignificantDigits: 3, expected: "0"}, + {minimumSignificantDigits: 1, maximumSignificantDigits: 4, expected: "0"}, + {minimumSignificantDigits: 1, maximumSignificantDigits: 5, expected: "0"}, + {minimumSignificantDigits: 2, maximumSignificantDigits: 2, expected: "0.0"}, + {minimumSignificantDigits: 2, maximumSignificantDigits: 3, expected: "0.0"}, + {minimumSignificantDigits: 2, maximumSignificantDigits: 4, expected: "0.0"}, + {minimumSignificantDigits: 2, maximumSignificantDigits: 5, expected: "0.0"}, + {minimumSignificantDigits: 3, maximumSignificantDigits: 3, expected: "0.00"}, + {minimumSignificantDigits: 3, maximumSignificantDigits: 4, expected: "0.00"}, + {minimumSignificantDigits: 3, maximumSignificantDigits: 5, expected: "0.00"}, +]; + +for (var i = 0; i < testData.length; i++) { + var min = testData[i].minimumSignificantDigits; + var max = testData[i].maximumSignificantDigits; + var options = {minimumSignificantDigits: min, maximumSignificantDigits: max}; + var format = new Intl.NumberFormat("en-US", options); + var actual = format.format(0); + var expected = testData[i].expected; + assertEq(actual, expected, + "Wrong formatted string for 0 with " + + "minimumSignificantDigits " + min + + ", maximumSignificantDigits " + max + + ": expected \"" + expected + + "\", actual \"" + actual + "\""); +} + +reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/supportedLocalesOf.js b/js/src/tests/non262/Intl/NumberFormat/supportedLocalesOf.js new file mode 100644 index 0000000000..5ba4470a98 --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/supportedLocalesOf.js @@ -0,0 +1,371 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")||xulRuntime.shell) +// -- test in browser only that ICU has locale data for all Mozilla languages + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// This array contains the locales that ICU supports in +// number formatting whose languages Mozilla localizes Firefox into. +// Current as of ICU 50.1.2 and Firefox March 2013. +var locales = [ + "af", + "af-NA", + "af-ZA", + "ar", + "ar-001", + "ar-AE", + "ar-BH", + "ar-DJ", + "ar-DZ", + "ar-EG", + "ar-EH", + "ar-ER", + "ar-IL", + "ar-IQ", + "ar-JO", + "ar-KM", + "ar-KW", + "ar-LB", + "ar-LY", + "ar-MA", + "ar-MR", + "ar-OM", + "ar-PS", + "ar-QA", + "ar-SA", + "ar-SD", + "ar-SO", + "ar-SY", + "ar-TD", + "ar-TN", + "ar-YE", + "as", + "as-IN", + "be", + "be-BY", + "bg", + "bg-BG", + "bn", + "bn-BD", + "bn-IN", + "br", + "br-FR", + "bs", + "bs-Cyrl", + "bs-Cyrl-BA", + "bs-Latn", + "bs-Latn-BA", + "ca", + "ca-AD", + "ca-ES", + "cs", + "cs-CZ", + "cy", + "cy-GB", + "da", + "da-DK", + "de", + "de-AT", + "de-BE", + "de-CH", + "de-DE", + "de-LI", + "de-LU", + "el", + "el-CY", + "el-GR", + "en", + "en-150", + "en-AG", + "en-AS", + "en-AU", + "en-BB", + "en-BE", + "en-BM", + "en-BS", + "en-BW", + "en-BZ", + "en-CA", + "en-CM", + "en-DM", + "en-FJ", + "en-FM", + "en-GB", + "en-GD", + "en-GG", + "en-GH", + "en-GI", + "en-GM", + "en-GU", + "en-GY", + "en-HK", + "en-IE", + "en-IM", + "en-IN", + "en-JE", + "en-JM", + "en-KE", + "en-KI", + "en-KN", + "en-KY", + "en-LC", + "en-LR", + "en-LS", + "en-MG", + "en-MH", + "en-MP", + "en-MT", + "en-MU", + "en-MW", + "en-NA", + "en-NG", + "en-NZ", + "en-PG", + "en-PH", + "en-PK", + "en-PR", + "en-PW", + "en-SB", + "en-SC", + "en-SG", + "en-SL", + "en-SS", + "en-SZ", + "en-TC", + "en-TO", + "en-TT", + "en-TZ", + "en-UG", + "en-UM", + "en-US", + "en-US-POSIX", + "en-VC", + "en-VG", + "en-VI", + "en-VU", + "en-WS", + "en-ZA", + "en-ZM", + "en-ZW", + "eo", + "es", + "es-419", + "es-AR", + "es-BO", + "es-CL", + "es-CO", + "es-CR", + "es-CU", + "es-DO", + "es-EA", + "es-EC", + "es-ES", + "es-GQ", + "es-GT", + "es-HN", + "es-IC", + "es-MX", + "es-NI", + "es-PA", + "es-PE", + "es-PH", + "es-PR", + "es-PY", + "es-SV", + "es-US", + "es-UY", + "es-VE", + "et", + "et-EE", + "eu", + "eu-ES", + "fa", + "fa-AF", + "fa-IR", + "ff", + "ff-SN", + "fi", + "fi-FI", + "fr", + "fr-BE", + "fr-BF", + "fr-BI", + "fr-BJ", + "fr-BL", + "fr-CA", + "fr-CD", + "fr-CF", + "fr-CG", + "fr-CH", + "fr-CI", + "fr-CM", + "fr-DJ", + "fr-DZ", + "fr-FR", + "fr-GA", + "fr-GF", + "fr-GN", + "fr-GP", + "fr-GQ", + "fr-HT", + "fr-KM", + "fr-LU", + "fr-MA", + "fr-MC", + "fr-MF", + "fr-MG", + "fr-ML", + "fr-MQ", + "fr-MR", + "fr-MU", + "fr-NC", + "fr-NE", + "fr-PF", + "fr-RE", + "fr-RW", + "fr-SC", + "fr-SN", + "fr-SY", + "fr-TD", + "fr-TG", + "fr-TN", + "fr-VU", + "fr-YT", + "ga", + "ga-IE", + "gl", + "gl-ES", + "gu", + "gu-IN", + "he", + "he-IL", + "hi", + "hi-IN", + "hr", + "hr-BA", + "hr-HR", + "hu", + "hu-HU", + "hy", + "hy-AM", + "id", + "id-ID", + "is", + "is-IS", + "it", + "it-CH", + "it-IT", + "it-SM", + "ja", + "ja-JP", + "kk", + "kk-Cyrl", + "kk-Cyrl-KZ", + "km", + "km-KH", + "kn", + "kn-IN", + "ko", + "ko-KP", + "ko-KR", + "lt", + "lt-LT", + "lv", + "lv-LV", + "mk", + "mk-MK", + "ml", + "ml-IN", + "mr", + "mr-IN", + "nb", + "nb-NO", + "nl", + "nl-AW", + "nl-BE", + "nl-CW", + "nl-NL", + "nl-SR", + "nl-SX", + "nn", + "nn-NO", + "or", + "or-IN", + "pa", + "pa-Arab", + "pa-Arab-PK", + "pa-Guru", + "pa-Guru-IN", + "pl", + "pl-PL", + "pt", + "pt-AO", + "pt-BR", + "pt-CV", + "pt-GW", + "pt-MO", + "pt-MZ", + "pt-PT", + "pt-ST", + "pt-TL", + "rm", + "rm-CH", + "ro", + "ro-MD", + "ro-RO", + "ru", + "ru-BY", + "ru-KG", + "ru-KZ", + "ru-MD", + "ru-RU", + "ru-UA", + "si", + "si-LK", + "sk", + "sk-SK", + "sl", + "sl-SI", + "sq", + "sq-AL", + "sq-MK", + "sr", + "sr-Cyrl", + "sr-Cyrl-BA", + "sr-Cyrl-ME", + "sr-Cyrl-RS", + "sr-Latn", + "sr-Latn-BA", + "sr-Latn-ME", + "sr-Latn-RS", + "sv", + "sv-AX", + "sv-FI", + "sv-SE", + "te", + "te-IN", + "th", + "th-TH", + "tr", + "tr-CY", + "tr-TR", + "uk", + "uk-UA", + "vi", + "vi-VN", + "zh", + "zh-Hans", + "zh-Hans-CN", + "zh-Hans-HK", + "zh-Hans-MO", + "zh-Hans-SG", + "zh-Hant", + "zh-Hant-HK", + "zh-Hant-MO", + "zh-Hant-TW", +]; + +var count = Intl.NumberFormat.supportedLocalesOf(locales).length; + +reportCompare(locales.length, count, "Number of supported locales in Intl.NumberFormat"); diff --git a/js/src/tests/non262/Intl/NumberFormat/toStringTag.js b/js/src/tests/non262/Intl/NumberFormat/toStringTag.js new file mode 100644 index 0000000000..9ad0901a0b --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/toStringTag.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var desc = Object.getOwnPropertyDescriptor(Intl.NumberFormat.prototype, Symbol.toStringTag); + +assertEq(desc !== undefined, true); +assertEq(desc.value, "Intl.NumberFormat"); +assertEq(desc.writable, false); +assertEq(desc.enumerable, false); +assertEq(desc.configurable, true); + +assertEq(Object.prototype.toString.call(Intl.NumberFormat.prototype), "[object Intl.NumberFormat]"); +assertEq(Object.prototype.toString.call(new Intl.NumberFormat), "[object Intl.NumberFormat]"); + +Object.defineProperty(Intl.NumberFormat.prototype, Symbol.toStringTag, {value: "NumberFormat"}); + +assertEq(Object.prototype.toString.call(Intl.NumberFormat.prototype), "[object NumberFormat]"); +assertEq(Object.prototype.toString.call(new Intl.NumberFormat), "[object NumberFormat]"); + +delete Intl.NumberFormat.prototype[Symbol.toStringTag]; + +assertEq(Object.prototype.toString.call(Intl.NumberFormat.prototype), "[object Object]"); +assertEq(Object.prototype.toString.call(new Intl.NumberFormat), "[object Object]"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/trailing-zero-display.js b/js/src/tests/non262/Intl/NumberFormat/trailing-zero-display.js new file mode 100644 index 0000000000..666053971d --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/trailing-zero-display.js @@ -0,0 +1,98 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// "stripIfInteger" with fractional digits. +{ + let nf1 = new Intl.NumberFormat("en", { + minimumFractionDigits: 2, + }); + + let nf2 = new Intl.NumberFormat("en", { + minimumFractionDigits: 2, + trailingZeroDisplay: "auto", + }); + + let nf3 = new Intl.NumberFormat("en", { + minimumFractionDigits: 2, + trailingZeroDisplay: "stripIfInteger", + }); + + assertEq(nf1.resolvedOptions().trailingZeroDisplay, "auto"); + assertEq(nf2.resolvedOptions().trailingZeroDisplay, "auto"); + assertEq(nf3.resolvedOptions().trailingZeroDisplay, "stripIfInteger"); + + assertEq(nf1.format(123), "123.00"); + assertEq(nf2.format(123), "123.00"); + assertEq(nf3.format(123), "123"); +} + +// "stripIfInteger" with significand digits. +{ + let nf1 = new Intl.NumberFormat("en", { + minimumSignificantDigits: 2, + }); + + let nf2 = new Intl.NumberFormat("en", { + minimumSignificantDigits: 2, + trailingZeroDisplay: "auto", + }); + + let nf3 = new Intl.NumberFormat("en", { + minimumSignificantDigits: 2, + trailingZeroDisplay: "stripIfInteger", + }); + + assertEq(nf1.resolvedOptions().trailingZeroDisplay, "auto"); + assertEq(nf2.resolvedOptions().trailingZeroDisplay, "auto"); + assertEq(nf3.resolvedOptions().trailingZeroDisplay, "stripIfInteger"); + + assertEq(nf1.format(1), "1.0"); + assertEq(nf2.format(1), "1.0"); + assertEq(nf3.format(1), "1"); +} + +// "stripIfInteger" with rounding increment. +{ + let nf1 = new Intl.NumberFormat("en", { + minimumFractionDigits: 2, + maximumFractionDigits: 2, + roundingIncrement: 5, + }); + let nf2 = new Intl.NumberFormat("en", { + minimumFractionDigits: 2, + maximumFractionDigits: 2, + roundingIncrement: 5, + trailingZeroDisplay: "auto", + }); + let nf3 = new Intl.NumberFormat("en", { + minimumFractionDigits: 2, + maximumFractionDigits: 2, + roundingIncrement: 5, + trailingZeroDisplay: "stripIfInteger", + }); + + assertEq(nf1.resolvedOptions().trailingZeroDisplay, "auto"); + assertEq(nf2.resolvedOptions().trailingZeroDisplay, "auto"); + assertEq(nf3.resolvedOptions().trailingZeroDisplay, "stripIfInteger"); + + // NB: Tests 1.975 twice b/c of . + + assertEq(nf1.format(1.975), "2.00"); + assertEq(nf1.format(1.97), "1.95"); + assertEq(nf1.format(1.975), "2.00"); + + assertEq(nf2.format(1.975), "2.00"); + assertEq(nf2.format(1.97), "1.95"); + assertEq(nf2.format(1.975), "2.00"); + + assertEq(nf3.format(1.975), "2"); + assertEq(nf3.format(1.97), "1.95"); + assertEq(nf3.format(1.975), "2"); +} + +// Invalid values. +for (let trailingZeroDisplay of ["", "true", true, "none", "yes", "no"]){ + assertThrowsInstanceOf(() => new Intl.NumberFormat("en", {trailingZeroDisplay}), RangeError); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/unit-compound-combinations.js b/js/src/tests/non262/Intl/NumberFormat/unit-compound-combinations.js new file mode 100644 index 0000000000..2aad94b98e --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/unit-compound-combinations.js @@ -0,0 +1,65 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Generated by make_intl_data.py. DO NOT EDIT. + +const sanctionedSimpleUnitIdentifiers = [ + "acre", + "bit", + "byte", + "celsius", + "centimeter", + "day", + "degree", + "fahrenheit", + "fluid-ounce", + "foot", + "gallon", + "gigabit", + "gigabyte", + "gram", + "hectare", + "hour", + "inch", + "kilobit", + "kilobyte", + "kilogram", + "kilometer", + "liter", + "megabit", + "megabyte", + "meter", + "microsecond", + "mile", + "mile-scandinavian", + "milliliter", + "millimeter", + "millisecond", + "minute", + "month", + "nanosecond", + "ounce", + "percent", + "petabyte", + "pound", + "second", + "stone", + "terabit", + "terabyte", + "week", + "yard", + "year" +]; + +// Test all simple unit identifier combinations are allowed. + +for (const numerator of sanctionedSimpleUnitIdentifiers) { + for (const denominator of sanctionedSimpleUnitIdentifiers) { + const unit = `${numerator}-per-${denominator}`; + const nf = new Intl.NumberFormat("en", {style: "unit", unit}); + + assertEq(nf.format(1), nf.formatToParts(1).map(p => p.value).join("")); + } +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/unit-formatToParts-has-unit-field.js b/js/src/tests/non262/Intl/NumberFormat/unit-formatToParts-has-unit-field.js new file mode 100644 index 0000000000..9292c8ac73 --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/unit-formatToParts-has-unit-field.js @@ -0,0 +1,90 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Generated by make_intl_data.py. DO NOT EDIT. + +const sanctionedSimpleUnitIdentifiers = [ + "acre", + "bit", + "byte", + "celsius", + "centimeter", + "day", + "degree", + "fahrenheit", + "fluid-ounce", + "foot", + "gallon", + "gigabit", + "gigabyte", + "gram", + "hectare", + "hour", + "inch", + "kilobit", + "kilobyte", + "kilogram", + "kilometer", + "liter", + "megabit", + "megabyte", + "meter", + "microsecond", + "mile", + "mile-scandinavian", + "milliliter", + "millimeter", + "millisecond", + "minute", + "month", + "nanosecond", + "ounce", + "percent", + "petabyte", + "pound", + "second", + "stone", + "terabit", + "terabyte", + "week", + "yard", + "year" +]; + +// Test only English and Chinese to keep the overall runtime reasonable. +// +// Chinese is included because it contains more than one "unit" element for +// certain unit combinations. +const locales = ["en", "zh"]; + +// Plural rules for English only differentiate between "one" and "other". Plural +// rules for Chinese only use "other". That means we only need to test two values +// per unit. +const values = [0, 1]; + +// Ensure unit formatters contain at least one "unit" element. + +for (const locale of locales) { + for (const unit of sanctionedSimpleUnitIdentifiers) { + const nf = new Intl.NumberFormat(locale, {style: "unit", unit}); + + for (const value of values) { + assertEq(nf.formatToParts(value).some(e => e.type === "unit"), true, + `locale=${locale}, unit=${unit}`); + } + } + + for (const numerator of sanctionedSimpleUnitIdentifiers) { + for (const denominator of sanctionedSimpleUnitIdentifiers) { + const unit = `${numerator}-per-${denominator}`; + const nf = new Intl.NumberFormat(locale, {style: "unit", unit}); + + for (const value of values) { + assertEq(nf.formatToParts(value).some(e => e.type === "unit"), true, + `locale=${locale}, unit=${unit}`); + } + } + } +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/unit-well-formed.js b/js/src/tests/non262/Intl/NumberFormat/unit-well-formed.js new file mode 100644 index 0000000000..8eca3b58cf --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/unit-well-formed.js @@ -0,0 +1,267 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Generated by make_intl_data.py. DO NOT EDIT. + +const sanctionedSimpleUnitIdentifiers = [ + "acre", + "bit", + "byte", + "celsius", + "centimeter", + "day", + "degree", + "fahrenheit", + "fluid-ounce", + "foot", + "gallon", + "gigabit", + "gigabyte", + "gram", + "hectare", + "hour", + "inch", + "kilobit", + "kilobyte", + "kilogram", + "kilometer", + "liter", + "megabit", + "megabyte", + "meter", + "microsecond", + "mile", + "mile-scandinavian", + "milliliter", + "millimeter", + "millisecond", + "minute", + "month", + "nanosecond", + "ounce", + "percent", + "petabyte", + "pound", + "second", + "stone", + "terabit", + "terabyte", + "week", + "yard", + "year" +]; + +const allUnits = [ + "acceleration-g-force", + "acceleration-meter-per-square-second", + "angle-arc-minute", + "angle-arc-second", + "angle-degree", + "angle-radian", + "angle-revolution", + "area-acre", + "area-dunam", + "area-hectare", + "area-square-centimeter", + "area-square-foot", + "area-square-inch", + "area-square-kilometer", + "area-square-meter", + "area-square-mile", + "area-square-yard", + "concentr-item", + "concentr-karat", + "concentr-milligram-ofglucose-per-deciliter", + "concentr-millimole-per-liter", + "concentr-mole", + "concentr-percent", + "concentr-permille", + "concentr-permillion", + "concentr-permyriad", + "consumption-liter-per-100-kilometer", + "consumption-liter-per-kilometer", + "consumption-mile-per-gallon", + "consumption-mile-per-gallon-imperial", + "digital-bit", + "digital-byte", + "digital-gigabit", + "digital-gigabyte", + "digital-kilobit", + "digital-kilobyte", + "digital-megabit", + "digital-megabyte", + "digital-petabyte", + "digital-terabit", + "digital-terabyte", + "duration-century", + "duration-day", + "duration-day-person", + "duration-decade", + "duration-hour", + "duration-microsecond", + "duration-millisecond", + "duration-minute", + "duration-month", + "duration-month-person", + "duration-nanosecond", + "duration-quarter", + "duration-second", + "duration-week", + "duration-week-person", + "duration-year", + "duration-year-person", + "electric-ampere", + "electric-milliampere", + "electric-ohm", + "electric-volt", + "energy-british-thermal-unit", + "energy-calorie", + "energy-electronvolt", + "energy-foodcalorie", + "energy-joule", + "energy-kilocalorie", + "energy-kilojoule", + "energy-kilowatt-hour", + "energy-therm-us", + "force-kilowatt-hour-per-100-kilometer", + "force-newton", + "force-pound-force", + "frequency-gigahertz", + "frequency-hertz", + "frequency-kilohertz", + "frequency-megahertz", + "graphics-dot", + "graphics-dot-per-centimeter", + "graphics-dot-per-inch", + "graphics-em", + "graphics-megapixel", + "graphics-pixel", + "graphics-pixel-per-centimeter", + "graphics-pixel-per-inch", + "length-astronomical-unit", + "length-centimeter", + "length-decimeter", + "length-earth-radius", + "length-fathom", + "length-foot", + "length-furlong", + "length-inch", + "length-kilometer", + "length-light-year", + "length-meter", + "length-micrometer", + "length-mile", + "length-mile-scandinavian", + "length-millimeter", + "length-nanometer", + "length-nautical-mile", + "length-parsec", + "length-picometer", + "length-point", + "length-solar-radius", + "length-yard", + "light-candela", + "light-lumen", + "light-lux", + "light-solar-luminosity", + "mass-carat", + "mass-dalton", + "mass-earth-mass", + "mass-grain", + "mass-gram", + "mass-kilogram", + "mass-microgram", + "mass-milligram", + "mass-ounce", + "mass-ounce-troy", + "mass-pound", + "mass-solar-mass", + "mass-stone", + "mass-ton", + "mass-tonne", + "power-gigawatt", + "power-horsepower", + "power-kilowatt", + "power-megawatt", + "power-milliwatt", + "power-watt", + "pressure-atmosphere", + "pressure-bar", + "pressure-hectopascal", + "pressure-inch-ofhg", + "pressure-kilopascal", + "pressure-megapascal", + "pressure-millibar", + "pressure-millimeter-ofhg", + "pressure-pascal", + "pressure-pound-force-per-square-inch", + "speed-kilometer-per-hour", + "speed-knot", + "speed-meter-per-second", + "speed-mile-per-hour", + "temperature-celsius", + "temperature-fahrenheit", + "temperature-generic", + "temperature-kelvin", + "torque-newton-meter", + "torque-pound-force-foot", + "volume-acre-foot", + "volume-barrel", + "volume-bushel", + "volume-centiliter", + "volume-cubic-centimeter", + "volume-cubic-foot", + "volume-cubic-inch", + "volume-cubic-kilometer", + "volume-cubic-meter", + "volume-cubic-mile", + "volume-cubic-yard", + "volume-cup", + "volume-cup-metric", + "volume-deciliter", + "volume-dessert-spoon", + "volume-dessert-spoon-imperial", + "volume-dram", + "volume-drop", + "volume-fluid-ounce", + "volume-fluid-ounce-imperial", + "volume-gallon", + "volume-gallon-imperial", + "volume-hectoliter", + "volume-jigger", + "volume-liter", + "volume-megaliter", + "volume-milliliter", + "volume-pinch", + "volume-pint", + "volume-pint-metric", + "volume-quart", + "volume-quart-imperial", + "volume-tablespoon", + "volume-teaspoon" +]; + +// Test only sanctioned unit identifiers are allowed. + +for (const typeAndUnit of allUnits) { + const [_, type, unit] = typeAndUnit.match(/(\w+)-(.+)/); + + let allowed; + if (unit.includes("-per-")) { + const [numerator, denominator] = unit.split("-per-"); + allowed = sanctionedSimpleUnitIdentifiers.includes(numerator) && + sanctionedSimpleUnitIdentifiers.includes(denominator); + } else { + allowed = sanctionedSimpleUnitIdentifiers.includes(unit); + } + + if (allowed) { + const nf = new Intl.NumberFormat("en", {style: "unit", unit}); + assertEq(nf.format(1), nf.formatToParts(1).map(p => p.value).join("")); + } else { + assertThrowsInstanceOf(() => new Intl.NumberFormat("en", {style: "unit", unit}), + RangeError, `Missing error for "${typeAndUnit}"`); + } +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/unit.js b/js/src/tests/non262/Intl/NumberFormat/unit.js new file mode 100644 index 0000000000..7abc5142e0 --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/unit.js @@ -0,0 +1,104 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const { + Nan, Inf, Integer, MinusSign, PlusSign, Literal, + Unit +} = NumberFormatParts; + +const testcases = [ + { + locale: "en", + options: { + style: "unit", + unit: "meter", + unitDisplay: "short", + }, + values: [ + {value: +0, string: "0 m", parts: [Integer("0"), Literal(" "), Unit("m")]}, + {value: -0, string: "-0 m", parts: [MinusSign("-"), Integer("0"), Literal(" "), Unit("m")]}, + {value: 0n, string: "0 m", parts: [Integer("0"), Literal(" "), Unit("m")]}, + + {value: 1, string: "1 m", parts: [Integer("1"), Literal(" "), Unit("m")]}, + {value: -1, string: "-1 m", parts: [MinusSign("-"), Integer("1"), Literal(" "), Unit("m")]}, + {value: 1n, string: "1 m", parts: [Integer("1"), Literal(" "), Unit("m")]}, + {value: -1n, string: "-1 m", parts: [MinusSign("-"), Integer("1"), Literal(" "), Unit("m")]}, + + {value: Infinity, string: "∞ m", parts: [Inf("∞"), Literal(" "), Unit("m")]}, + {value: -Infinity, string: "-∞ m", parts: [MinusSign("-"), Inf("∞"), Literal(" "), Unit("m")]}, + + {value: NaN, string: "NaN m", parts: [Nan("NaN"), Literal(" "), Unit("m")]}, + {value: -NaN, string: "NaN m", parts: [Nan("NaN"), Literal(" "), Unit("m")]}, + ], + }, + + { + locale: "en", + options: { + style: "unit", + unit: "meter", + unitDisplay: "narrow", + }, + values: [ + {value: +0, string: "0m", parts: [Integer("0"), Unit("m")]}, + {value: -0, string: "-0m", parts: [MinusSign("-"), Integer("0"), Unit("m")]}, + {value: 0n, string: "0m", parts: [Integer("0"), Unit("m")]}, + + {value: 1, string: "1m", parts: [Integer("1"), Unit("m")]}, + {value: -1, string: "-1m", parts: [MinusSign("-"), Integer("1"), Unit("m")]}, + {value: 1n, string: "1m", parts: [Integer("1"), Unit("m")]}, + {value: -1n, string: "-1m", parts: [MinusSign("-"), Integer("1"), Unit("m")]}, + + {value: Infinity, string: "∞m", parts: [Inf("∞"), Unit("m")]}, + {value: -Infinity, string: "-∞m", parts: [MinusSign("-"), Inf("∞"), Unit("m")]}, + + {value: NaN, string: "NaNm", parts: [Nan("NaN"), Unit("m")]}, + {value: -NaN, string: "NaNm", parts: [Nan("NaN"), Unit("m")]}, + ], + }, + + { + locale: "en", + options: { + style: "unit", + unit: "meter", + unitDisplay: "long", + }, + values: [ + {value: +0, string: "0 meters", parts: [Integer("0"), Literal(" "), Unit("meters")]}, + {value: -0, string: "-0 meters", parts: [MinusSign("-"), Integer("0"), Literal(" "), Unit("meters")]}, + {value: 0n, string: "0 meters", parts: [Integer("0"), Literal(" "), Unit("meters")]}, + + {value: 1, string: "1 meter", parts: [Integer("1"), Literal(" "), Unit("meter")]}, + {value: -1, string: "-1 meter", parts: [MinusSign("-"), Integer("1"), Literal(" "), Unit("meter")]}, + {value: 1n, string: "1 meter", parts: [Integer("1"), Literal(" "), Unit("meter")]}, + {value: -1n, string: "-1 meter", parts: [MinusSign("-"), Integer("1"), Literal(" "), Unit("meter")]}, + + {value: Infinity, string: "∞ meters", parts: [Inf("∞"), Literal(" "), Unit("meters")]}, + {value: -Infinity, string: "-∞ meters", parts: [MinusSign("-"), Inf("∞"), Literal(" "), Unit("meters")]}, + + {value: NaN, string: "NaN meters", parts: [Nan("NaN"), Literal(" "), Unit("meters")]}, + {value: -NaN, string: "NaN meters", parts: [Nan("NaN"), Literal(" "), Unit("meters")]}, + ], + }, + + // Ensure the correct compound unit is automatically selected by ICU. For + // example instead of "50 chilometri al orari", 50 km/h should return + // "50 chilometri orari" in Italian. + + { + locale: "it", + options: { + style: "unit", + unit: "kilometer-per-hour", + unitDisplay: "long", + }, + values: [ + {value: 50, string: "50 chilometri orari", parts: [Integer("50"), Literal(" "), Unit("chilometri orari")]}, + ], + }, +]; + +runNumberFormattingTestcases(testcases); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/unwrapping.js b/js/src/tests/non262/Intl/NumberFormat/unwrapping.js new file mode 100644 index 0000000000..df0b15d6fc --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/unwrapping.js @@ -0,0 +1,248 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Test UnwrapNumberFormat operation. + +const numberFormatFunctions = []; +numberFormatFunctions.push({ + function: Intl.NumberFormat.prototype.resolvedOptions, + unwrap: true, +}); +numberFormatFunctions.push({ + function: Object.getOwnPropertyDescriptor(Intl.NumberFormat.prototype, "format").get, + unwrap: true, +}); +numberFormatFunctions.push({ + function: Intl.NumberFormat.prototype.formatToParts, + unwrap: false, +}); + +function IsIntlService(c) { + return typeof c === "function" && + c.hasOwnProperty("prototype") && + c.prototype.hasOwnProperty("resolvedOptions"); +} + +function IsObject(o) { + return Object(o) === o; +} + +function IsPrimitive(o) { + return Object(o) !== o; +} + +function intlObjects(ctor) { + let args = []; + if (ctor === Intl.DisplayNames) { + // Intl.DisplayNames can't be constructed without any arguments. + args = [undefined, {type: "language"}]; + } + + return [ + // Instance of an Intl constructor. + new ctor(...args), + + // Instance of a subclassed Intl constructor. + new class extends ctor {}(...args), + + // Intl object not inheriting from its default prototype. + Object.setPrototypeOf(new ctor(...args), Object.prototype), + ]; +} + +function thisValues(C) { + const intlConstructors = Object.getOwnPropertyNames(Intl).map(name => Intl[name]).filter(IsIntlService); + + return [ + // Primitive values. + ...[undefined, null, true, "abc", Symbol(), 123], + + // Object values. + ...[{}, [], /(?:)/, function(){}, new Proxy({}, {})], + + // Intl objects. + ...[].concat(...intlConstructors.filter(ctor => ctor !== C).map(intlObjects)), + + // Object inheriting from an Intl constructor prototype. + ...intlConstructors.map(ctor => Object.create(ctor.prototype)), + ]; +} + +const intlFallbackSymbol = Object.getOwnPropertySymbols(Intl.NumberFormat.call(Object.create(Intl.NumberFormat.prototype)))[0]; + +// Test Intl.NumberFormat.prototype methods. +for (let {function: numberFormatFunction, unwrap} of numberFormatFunctions) { + // Test a TypeError is thrown when the this-value isn't an initialized + // Intl.NumberFormat instance. + for (let thisValue of thisValues(Intl.NumberFormat)) { + assertThrowsInstanceOf(() => numberFormatFunction.call(thisValue), TypeError); + } + + // And test no error is thrown for initialized Intl.NumberFormat instances. + for (let thisValue of intlObjects(Intl.NumberFormat)) { + numberFormatFunction.call(thisValue); + } + + // Manually add [[FallbackSymbol]] to objects and then repeat the tests from above. + for (let thisValue of thisValues(Intl.NumberFormat)) { + assertThrowsInstanceOf(() => numberFormatFunction.call({ + __proto__: Intl.NumberFormat.prototype, + [intlFallbackSymbol]: thisValue, + }), TypeError); + } + + for (let thisValue of intlObjects(Intl.NumberFormat)) { + let obj = { + __proto__: Intl.NumberFormat.prototype, + [intlFallbackSymbol]: thisValue, + }; + if (unwrap) { + numberFormatFunction.call(obj); + } else { + assertThrowsInstanceOf(() => numberFormatFunction.call(obj), TypeError); + } + } + + // Ensure [[FallbackSymbol]] isn't retrieved for Intl.NumberFormat instances. + for (let thisValue of intlObjects(Intl.NumberFormat)) { + Object.defineProperty(thisValue, intlFallbackSymbol, { + get() { assertEq(false, true); } + }); + numberFormatFunction.call(thisValue); + } + + // Ensure [[FallbackSymbol]] is only retrieved for objects inheriting from Intl.NumberFormat.prototype. + for (let thisValue of thisValues(Intl.NumberFormat).filter(IsObject)) { + if (Intl.NumberFormat.prototype.isPrototypeOf(thisValue)) + continue; + Object.defineProperty(thisValue, intlFallbackSymbol, { + get() { assertEq(false, true); } + }); + assertThrowsInstanceOf(() => numberFormatFunction.call(thisValue), TypeError); + } + + // Repeat the test from above, but also change Intl.NumberFormat[@@hasInstance] + // so it always returns |true|. + for (let thisValue of thisValues(Intl.NumberFormat).filter(IsObject)) { + let isPrototypeOf = Intl.NumberFormat.prototype.isPrototypeOf(thisValue); + let hasInstanceCalled = false, symbolGetterCalled = false; + Object.defineProperty(Intl.NumberFormat, Symbol.hasInstance, { + value() { + assertEq(hasInstanceCalled, false); + hasInstanceCalled = true; + return true; + }, configurable: true + }); + Object.defineProperty(thisValue, intlFallbackSymbol, { + get() { + assertEq(symbolGetterCalled, false); + symbolGetterCalled = true; + return null; + }, configurable: true + }); + + assertThrowsInstanceOf(() => numberFormatFunction.call(thisValue), TypeError); + + delete Intl.NumberFormat[Symbol.hasInstance]; + + assertEq(hasInstanceCalled, false); + assertEq(symbolGetterCalled, unwrap && isPrototypeOf); + } + + // Test with primitive values. + for (let thisValue of thisValues(Intl.NumberFormat).filter(IsPrimitive)) { + // Ensure @@hasInstance is not called. + Object.defineProperty(Intl.NumberFormat, Symbol.hasInstance, { + value() { assertEq(true, false); }, configurable: true + }); + let isUndefinedOrNull = thisValue === undefined || thisValue === null; + let symbolHolder; + if (!isUndefinedOrNull) { + // Ensure the fallback symbol isn't retrieved from the primitive wrapper prototype. + symbolHolder = Object.getPrototypeOf(thisValue); + Object.defineProperty(symbolHolder, intlFallbackSymbol, { + get() { assertEq(true, false); }, configurable: true + }); + } + + assertThrowsInstanceOf(() => numberFormatFunction.call(thisValue), TypeError); + + delete Intl.NumberFormat[Symbol.hasInstance]; + if (!isUndefinedOrNull) + delete symbolHolder[intlFallbackSymbol]; + } +} + +// Test format() returns the correct result for objects initialized as Intl.NumberFormat instances. +{ + // An actual Intl.NumberFormat instance. + let numberFormat = new Intl.NumberFormat(); + + // An object initialized as a NumberFormat instance. + let thisValue = Object.create(Intl.NumberFormat.prototype); + Intl.NumberFormat.call(thisValue); + + // Object with [[FallbackSymbol]] set to NumberFormat instance. + let fakeObj = { + __proto__: Intl.NumberFormat.prototype, + [intlFallbackSymbol]: numberFormat, + }; + + for (let number of [0, 1, 1.5, Infinity, NaN]) { + let expected = numberFormat.format(number); + assertEq(thisValue.format(number), expected); + assertEq(thisValue[intlFallbackSymbol].format(number), expected); + assertEq(fakeObj.format(number), expected); + } +} + +// Ensure formatToParts() doesn't use the fallback semantics. +{ + let formatToParts = Intl.NumberFormat.prototype.formatToParts; + + // An object initialized as a NumberFormat instance. + let thisValue = Object.create(Intl.NumberFormat.prototype); + Intl.NumberFormat.call(thisValue); + assertThrowsInstanceOf(() => formatToParts.call(thisValue), TypeError); + + // Object with [[FallbackSymbol]] set to NumberFormat instance. + let fakeObj = { + __proto__: Intl.NumberFormat.prototype, + [intlFallbackSymbol]: new Intl.NumberFormat(), + }; + assertThrowsInstanceOf(() => formatToParts.call(fakeObj), TypeError); +} + +// Test resolvedOptions() returns the same results. +{ + // An actual Intl.NumberFormat instance. + let numberFormat = new Intl.NumberFormat(); + + // An object initialized as a NumberFormat instance. + let thisValue = Object.create(Intl.NumberFormat.prototype); + Intl.NumberFormat.call(thisValue); + + // Object with [[FallbackSymbol]] set to NumberFormat instance. + let fakeObj = { + __proto__: Intl.NumberFormat.prototype, + [intlFallbackSymbol]: numberFormat, + }; + + function assertEqOptions(actual, expected) { + actual = Object.entries(actual); + expected = Object.entries(expected); + + assertEq(actual.length, expected.length, "options count mismatch"); + for (var i = 0; i < expected.length; i++) { + assertEq(actual[i][0], expected[i][0], "key mismatch at " + i); + assertEq(actual[i][1], expected[i][1], "value mismatch at " + i); + } + } + + let expected = numberFormat.resolvedOptions(); + assertEqOptions(thisValue.resolvedOptions(), expected); + assertEqOptions(thisValue[intlFallbackSymbol].resolvedOptions(), expected); + assertEqOptions(fakeObj.resolvedOptions(), expected); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/use-grouping-bool-string.js b/js/src/tests/non262/Intl/NumberFormat/use-grouping-bool-string.js new file mode 100644 index 0000000000..4216c874f0 --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/use-grouping-bool-string.js @@ -0,0 +1,10 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +let nf1 = new Intl.NumberFormat("en", {useGrouping: "true"}); +assertEq(nf1.format(1000), "1,000"); + +let nf2 = new Intl.NumberFormat("en", {useGrouping: "false"}); +assertEq(nf2.format(1000), "1,000"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/NumberFormat/use-grouping.js b/js/src/tests/non262/Intl/NumberFormat/use-grouping.js new file mode 100644 index 0000000000..b10398dc67 --- /dev/null +++ b/js/src/tests/non262/Intl/NumberFormat/use-grouping.js @@ -0,0 +1,101 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const tests = { + // minimumGroupingDigits is one for "en" (English). + "en": { + values: [ + { + value: 1000, + useGroupings: { + auto: "1,000", + always: "1,000", + min2: "1000", + "": "1000", + }, + }, + { + value: 10000, + useGroupings: { + auto: "10,000", + always: "10,000", + min2: "10,000", + "": "10000", + }, + }, + ], + }, + + // minimumGroupingDigits is two for "pl" (Polish). + "pl": { + values: [ + { + value: 1000, + useGroupings: { + auto: "1000", + always: "1 000", + min2: "1000", + "": "1000", + }, + }, + { + value: 10000, + useGroupings: { + auto: "10 000", + always: "10 000", + min2: "10 000", + "": "10000", + }, + }, + ], + }, +}; + +for (let [locale, {options = {}, values}] of Object.entries(tests)) { + for (let {value, useGroupings} of values) { + for (let [useGrouping, expected] of Object.entries(useGroupings)) { + let nf = new Intl.NumberFormat(locale, {...options, useGrouping}); + assertEq(nf.format(value), expected, `locale=${locale}, value=${value}, useGrouping=${useGrouping}`); + } + } +} + +// Resolved options. +for (let [useGrouping, expected] of [ + [false, false], + ["", false], + [0, false], + [null, false], + + ["auto", "auto"], + [undefined, "auto"], + ["true", "auto"], + ["false", "auto"], + + ["always", "always"], + [true, "always"], + + ["min2", "min2"], +]) { + let nf = new Intl.NumberFormat("en", {useGrouping}); + assertEq(nf.resolvedOptions().useGrouping , expected); +} + +// Throws a RangeError for unsupported values. +for (let useGrouping of [ + "none", + "yes", + "no", + {}, + 123, + 123n, +]) { + assertThrowsInstanceOf(() => new Intl.NumberFormat("en", {useGrouping}), RangeError); +} + +// Throws a TypeError if ToString fails. +for (let useGrouping of [Object.create(null), Symbol()]) { + assertThrowsInstanceOf(() => new Intl.NumberFormat("en", {useGrouping}), TypeError); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/PluralRules/browser.js b/js/src/tests/non262/Intl/PluralRules/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Intl/PluralRules/call.js b/js/src/tests/non262/Intl/PluralRules/call.js new file mode 100644 index 0000000000..9412fa44d0 --- /dev/null +++ b/js/src/tests/non262/Intl/PluralRules/call.js @@ -0,0 +1,53 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +function IsIntlService(c) { + return typeof c === "function" && + c.hasOwnProperty("prototype") && + c.prototype.hasOwnProperty("resolvedOptions"); +} + +function thisValues() { + const intlConstructors = Object.getOwnPropertyNames(Intl).map(name => Intl[name]).filter(IsIntlService); + + return [ + // Primitive values. + ...[undefined, null, true, "abc", Symbol(), 123], + + // Object values. + ...[{}, [], /(?:)/, function(){}, new Proxy({}, {})], + + // Intl objects. + ...[].concat(...intlConstructors.map(ctor => { + let args = []; + if (ctor === Intl.DisplayNames) { + // Intl.DisplayNames can't be constructed without any arguments. + args = [undefined, {type: "language"}]; + } + + return [ + // Instance of an Intl constructor. + new ctor(...args), + + // Instance of a subclassed Intl constructor. + new class extends ctor {}(...args), + + // Object inheriting from an Intl constructor prototype. + Object.create(ctor.prototype), + + // Intl object not inheriting from its default prototype. + Object.setPrototypeOf(new ctor(...args), Object.prototype), + ]; + })), + ]; +} + +// Intl.PluralRules cannot be invoked as a function. +assertThrowsInstanceOf(() => Intl.PluralRules(), TypeError); + +// Also test with explicit this-value. +for (let thisValue of thisValues()) { + assertThrowsInstanceOf(() => Intl.PluralRules.call(thisValue), TypeError); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/PluralRules/construct-newtarget.js b/js/src/tests/non262/Intl/PluralRules/construct-newtarget.js new file mode 100644 index 0000000000..356c2dd221 --- /dev/null +++ b/js/src/tests/non262/Intl/PluralRules/construct-newtarget.js @@ -0,0 +1,76 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Test subclassing %Intl.PluralRules% works correctly. +class MyPluralRules extends Intl.PluralRules {} + +var obj = new MyPluralRules(); +assertEq(obj instanceof MyPluralRules, true); +assertEq(obj instanceof Intl.PluralRules, true); +assertEq(Object.getPrototypeOf(obj), MyPluralRules.prototype); + +obj = Reflect.construct(MyPluralRules, []); +assertEq(obj instanceof MyPluralRules, true); +assertEq(obj instanceof Intl.PluralRules, true); +assertEq(Object.getPrototypeOf(obj), MyPluralRules.prototype); + +obj = Reflect.construct(MyPluralRules, [], MyPluralRules); +assertEq(obj instanceof MyPluralRules, true); +assertEq(obj instanceof Intl.PluralRules, true); +assertEq(Object.getPrototypeOf(obj), MyPluralRules.prototype); + +obj = Reflect.construct(MyPluralRules, [], Intl.PluralRules); +assertEq(obj instanceof MyPluralRules, false); +assertEq(obj instanceof Intl.PluralRules, true); +assertEq(Object.getPrototypeOf(obj), Intl.PluralRules.prototype); + + +// Set a different constructor as NewTarget. +obj = Reflect.construct(MyPluralRules, [], Array); +assertEq(obj instanceof MyPluralRules, false); +assertEq(obj instanceof Intl.PluralRules, false); +assertEq(obj instanceof Array, true); +assertEq(Object.getPrototypeOf(obj), Array.prototype); + +obj = Reflect.construct(Intl.PluralRules, [], Array); +assertEq(obj instanceof Intl.PluralRules, false); +assertEq(obj instanceof Array, true); +assertEq(Object.getPrototypeOf(obj), Array.prototype); + + +// The prototype defaults to %PluralRulesPrototype% if null. +function NewTargetNullPrototype() {} +NewTargetNullPrototype.prototype = null; + +obj = Reflect.construct(Intl.PluralRules, [], NewTargetNullPrototype); +assertEq(obj instanceof Intl.PluralRules, true); +assertEq(Object.getPrototypeOf(obj), Intl.PluralRules.prototype); + +obj = Reflect.construct(MyPluralRules, [], NewTargetNullPrototype); +assertEq(obj instanceof MyPluralRules, false); +assertEq(obj instanceof Intl.PluralRules, true); +assertEq(Object.getPrototypeOf(obj), Intl.PluralRules.prototype); + + +// "prototype" property is retrieved exactly once. +var trapLog = [], getLog = []; +var ProxiedConstructor = new Proxy(Intl.PluralRules, new Proxy({ + get(target, propertyKey, receiver) { + getLog.push(propertyKey); + return Reflect.get(target, propertyKey, receiver); + } +}, { + get(target, propertyKey, receiver) { + trapLog.push(propertyKey); + return Reflect.get(target, propertyKey, receiver); + } +})); + +obj = Reflect.construct(Intl.PluralRules, [], ProxiedConstructor); +assertEqArray(trapLog, ["get"]); +assertEqArray(getLog, ["prototype"]); +assertEq(obj instanceof Intl.PluralRules, true); +assertEq(Object.getPrototypeOf(obj), Intl.PluralRules.prototype); + + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/PluralRules/cross-compartment.js b/js/src/tests/non262/Intl/PluralRules/cross-compartment.js new file mode 100644 index 0000000000..ff59f35957 --- /dev/null +++ b/js/src/tests/non262/Intl/PluralRules/cross-compartment.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +var otherGlobal = newGlobal(); + +var pluralRules = new Intl.PluralRules(); +var ccwPluralRules = new otherGlobal.Intl.PluralRules(); + +// Test Intl.PluralRules.prototype.select with a CCW object. +var Intl_PluralRules_select = Intl.PluralRules.prototype.select; + +assertEq(Intl_PluralRules_select.call(ccwPluralRules, 0), + Intl_PluralRules_select.call(pluralRules, 0)); + +// Test Intl.PluralRules.prototype.resolvedOptions with a CCW object. +var Intl_PluralRules_resolvedOptions = Intl.PluralRules.prototype.resolvedOptions; + +assertEq(deepEqual(Intl_PluralRules_resolvedOptions.call(ccwPluralRules), + Intl_PluralRules_resolvedOptions.call(pluralRules)), + true); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/PluralRules/negativeZeroFractionDigits.js b/js/src/tests/non262/Intl/PluralRules/negativeZeroFractionDigits.js new file mode 100644 index 0000000000..615e533466 --- /dev/null +++ b/js/src/tests/non262/Intl/PluralRules/negativeZeroFractionDigits.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const optionsList = [ + {minimumFractionDigits: -0, maximumFractionDigits: -0}, + {minimumFractionDigits: -0, maximumFractionDigits: +0}, + {minimumFractionDigits: +0, maximumFractionDigits: -0}, + {minimumFractionDigits: +0, maximumFractionDigits: +0}, +]; + +for (let options of optionsList) { + let pluralRules = new Intl.PluralRules("en-US", options); + + let {minimumFractionDigits, maximumFractionDigits} = pluralRules.resolvedOptions(); + assertEq(minimumFractionDigits, +0); + assertEq(maximumFractionDigits, +0); + + assertEq(pluralRules.select(123), "other"); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/PluralRules/number-options.js b/js/src/tests/non262/Intl/PluralRules/number-options.js new file mode 100644 index 0000000000..b3e18f183c --- /dev/null +++ b/js/src/tests/non262/Intl/PluralRules/number-options.js @@ -0,0 +1,134 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Test number-format options are accepted by Intl.PluralRules. + +for (let minimumIntegerDigits of [undefined, 1, 21]) { + for (let minimumFractionDigits of [undefined, 0, 20]) { + for (let maximumFractionDigits of [undefined, 0, 20]) { + for (let minimumSignificantDigits of [undefined, 0, 21]) { + for (let maximumSignificantDigits of [undefined, 0, 21]) { + for (let roundingPriority of [undefined, "morePrecision"]) { + for (let roundingIncrement of [undefined, 5000]) { + for (let roundingMode of [undefined, "trunc"]) { + for (let trailingZeroDisplay of [undefined, "stripIfInteger"]) { + let options = { + minimumIntegerDigits, + minimumFractionDigits, + maximumFractionDigits, + minimumSignificantDigits, + maximumSignificantDigits, + roundingPriority, + roundingIncrement, + roundingMode, + trailingZeroDisplay, + }; + + let pl; + try { + pl = new Intl.PluralRules("en", options); + } catch (e) { + // Ignore exception from conflicting options. + continue; + } + + // InitializePluralRules: + // 8. Perform ? SetNumberFormatDigitOptions(pluralRules, options, +0𝔽, 3𝔽, "standard"). + let mnfdDefault = 0; + let mxfdDefault = 3; + + // SetNumberFormatDigitOptions: + // 13. If roundingIncrement is not 1, set mxfdDefault to mnfdDefault. + if (roundingIncrement > 1) { + mxfdDefault = mnfdDefault; + } + + // 17. If mnsd is not undefined or mxsd is not undefined, then + // a. Let hasSd be true. + // 18. Else, + // a. Let hasSd be false. + let hasSd = minimumSignificantDigits !== undefined || maximumSignificantDigits !== undefined; + + // 21. Let needSd be true. + // 22. Let needFd be true. + let needSd = true; + let needFd = true; + + // 23. If roundingPriority is "auto", then + // a. Set needSd to hasSd. + // b. If needSd is true, or hasFd is false and notation is "compact", then + // i. Set needFd to false. + if ((roundingPriority ?? "auto") === "auto") { + needSd = hasSd; + if (needSd) { + needFd = false; + } + } + + // 24. If needSd is true, then + // a. If hasSd is true, then + // i. Set intlObj.[[MinimumSignificantDigits]] to ? DefaultNumberOption(mnsd, 1, 21, 1). + // ii. Set intlObj.[[MaximumSignificantDigits]] to ? DefaultNumberOption(mxsd, intlObj.[[MinimumSignificantDigits]], 21, 21). + // b. Else, + // i. Set intlObj.[[MinimumSignificantDigits]] to 1. + // ii. Set intlObj.[[MaximumSignificantDigits]] to 21. + let mnsd = undefined; + let mxsd = undefined; + if (needSd) { + mnsd = minimumSignificantDigits ?? 1; + mxsd = maximumSignificantDigits ?? 21; + } + + // 25. If needFd is true, then + // a. If hasFd is true, then + // i. Set mnfd to ? DefaultNumberOption(mnfd, 0, 20, undefined). + // ii. Set mxfd to ? DefaultNumberOption(mxfd, 0, 20, undefined). + // iii. If mnfd is undefined, set mnfd to min(mnfdDefault, mxfd). + // iv. Else if mxfd is undefined, set mxfd to max(mxfdDefault, mnfd). + // v. Else if mnfd is greater than mxfd, throw a RangeError exception. + // vi. Set intlObj.[[MinimumFractionDigits]] to mnfd. + // vii. Set intlObj.[[MaximumFractionDigits]] to mxfd. + // b. Else, + // i. Set intlObj.[[MinimumFractionDigits]] to mnfdDefault. + // ii. Set intlObj.[[MaximumFractionDigits]] to mxfdDefault. + let mnfd = undefined; + let mxfd = undefined; + if (needFd) { + mnfd = minimumFractionDigits ?? mnfdDefault; + mxfd = maximumFractionDigits ?? Math.max(mxfdDefault, mnfd); + } + + // 26. If needSd is false and needFd is false, then + // a. Set intlObj.[[MinimumFractionDigits]] to 0. + // b. Set intlObj.[[MaximumFractionDigits]] to 0. + // c. Set intlObj.[[MinimumSignificantDigits]] to 1. + // d. Set intlObj.[[MaximumSignificantDigits]] to 2. + // e. Set intlObj.[[RoundingType]] to morePrecision. + if (!needSd && !needFd) { + mnfd = 0; + mxfd = 0; + mnsd = 1; + mxsd = 2; + } + + let resolved = pl.resolvedOptions(); + assertEq(resolved.minimumIntegerDigits, minimumIntegerDigits ?? 1); + assertEq(resolved.minimumFractionDigits, mnfd); + assertEq(resolved.maximumFractionDigits, mxfd); + assertEq(resolved.minimumSignificantDigits, mnsd); + assertEq(resolved.maximumSignificantDigits, mxsd); + assertEq(resolved.roundingPriority, roundingPriority ?? "auto"); + assertEq(resolved.roundingIncrement, roundingIncrement ?? 1); + assertEq(resolved.roundingMode, roundingMode ?? "halfExpand"); + assertEq(resolved.trailingZeroDisplay, trailingZeroDisplay ?? "auto"); + } + } + } + } + } + } + } + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Intl/PluralRules/pluralrules.js b/js/src/tests/non262/Intl/PluralRules/pluralrules.js new file mode 100644 index 0000000000..20d6117b3b --- /dev/null +++ b/js/src/tests/non262/Intl/PluralRules/pluralrules.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Tests the format function with a diverse set of locales and options. + +var pr; + +pr = new Intl.PluralRules("en-us"); +assertEq(pr.resolvedOptions().locale, "en-US"); +assertEq(pr.resolvedOptions().type, "cardinal"); +assertEq(pr.resolvedOptions().pluralCategories.length, 2); + +pr = new Intl.PluralRules("de", {type: 'cardinal'}); +assertEq(pr.resolvedOptions().pluralCategories.length, 2); + +pr = new Intl.PluralRules("de", {type: 'ordinal'}); +assertEq(pr.resolvedOptions().pluralCategories.length, 1); + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Intl/PluralRules/resolvedOptions-overridden-species.js b/js/src/tests/non262/Intl/PluralRules/resolvedOptions-overridden-species.js new file mode 100644 index 0000000000..3591aba32b --- /dev/null +++ b/js/src/tests/non262/Intl/PluralRules/resolvedOptions-overridden-species.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Tests the PluralRules.resolvedOptions function for overriden Array[Symbol.species]. + +var pl = new Intl.PluralRules("de"); + +Object.defineProperty(Array, Symbol.species, { + value: function() { + return new Proxy(["?"], { + get(t, pk, r) { + return Reflect.get(t, pk, r); + }, + defineProperty(t, pk) { + return true; + } + }); + } +}); + +var pluralCategories = pl.resolvedOptions().pluralCategories; + +assertEqArray(pluralCategories, ["one", "other"]); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/PluralRules/rounding.js b/js/src/tests/non262/Intl/PluralRules/rounding.js new file mode 100644 index 0000000000..6f9b5f9936 --- /dev/null +++ b/js/src/tests/non262/Intl/PluralRules/rounding.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// The rounding mode defaults to half-up for both NumberFormat and PluralRules. + +var locale = "en"; +var options = {maximumFractionDigits: 0}; + +assertEq(new Intl.NumberFormat(locale, options).format(0), "0"); +assertEq(new Intl.NumberFormat(locale, options).format(0.5), "1"); +assertEq(new Intl.NumberFormat(locale, options).format(1), "1"); + +assertEq(new Intl.PluralRules(locale, options).select(0), "other"); +assertEq(new Intl.PluralRules(locale, options).select(0.5), "one"); +assertEq(new Intl.PluralRules(locale, options).select(1), "one"); + +if (typeof reportCompare === "function") + reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Intl/PluralRules/select.js b/js/src/tests/non262/Intl/PluralRules/select.js new file mode 100644 index 0000000000..dcc057ec3c --- /dev/null +++ b/js/src/tests/non262/Intl/PluralRules/select.js @@ -0,0 +1,63 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')) + +// Tests the format function with a diverse set of locales and options. + +var pr; + +pr = new Intl.PluralRules("en-us"); +assertEq(pr.select(0), "other"); +assertEq(pr.select(0.5), "other"); +assertEq(pr.select(1.2), "other"); +assertEq(pr.select(1.5), "other"); +assertEq(pr.select(1.7), "other"); +assertEq(pr.select(-1), "one"); +assertEq(pr.select(1), "one"); +assertEq(pr.select("1"), "one"); +assertEq(pr.select(123456789.123456789), "other"); + +pr = new Intl.PluralRules("de", {type: "cardinal"}); +assertEq(pr.select(0), "other"); +assertEq(pr.select(0.5), "other"); +assertEq(pr.select(1.2), "other"); +assertEq(pr.select(1.5), "other"); +assertEq(pr.select(1.7), "other"); +assertEq(pr.select(-1), "one"); + +pr = new Intl.PluralRules("de", {type: "ordinal"}); +assertEq(pr.select(0), "other"); +assertEq(pr.select(0.5), "other"); +assertEq(pr.select(1.2), "other"); +assertEq(pr.select(1.5), "other"); +assertEq(pr.select(1.7), "other"); +assertEq(pr.select(-1), "other"); + +pr = new Intl.PluralRules("pl", {type: "cardinal"}); +assertEq(pr.select(0), "many"); +assertEq(pr.select(0.5), "other"); +assertEq(pr.select(1), "one"); + +pr = new Intl.PluralRules("pl", {type: "cardinal", maximumFractionDigits: 0}); +assertEq(pr.select(1.1), "one"); + +pr = new Intl.PluralRules("pl", {type: "cardinal", maximumFractionDigits: 1}); +assertEq(pr.select(1.1), "other"); + +pr = new Intl.PluralRules("en", {type: "cardinal", minimumFractionDigits: 0}); +assertEq(pr.select(1), "one"); + +pr = new Intl.PluralRules("en", {type: "cardinal", minimumFractionDigits: 2}); +assertEq(pr.select(1), "other"); + +var weirdCases = [ + NaN, + Infinity, + "word", + [0,2], + {}, +]; + +for (let c of weirdCases) { + assertEq(pr.select(c), "other"); +}; + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Intl/PluralRules/selectRange.js b/js/src/tests/non262/Intl/PluralRules/selectRange.js new file mode 100644 index 0000000000..d07eef4019 --- /dev/null +++ b/js/src/tests/non262/Intl/PluralRules/selectRange.js @@ -0,0 +1,84 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')) + +// Any combination returns "other" for "en-US". +{ + let numbers = [0, 0.5, 1.2, 1.5, 1.7, -1, 1, "1", 123456789.123456789, Infinity, -Infinity]; + + const weirdCases = [ + NaN, + "word", + [0, 2], + {}, + ]; + + for (let type of ["ordinal", "cardinal"]) { + let pr = new Intl.PluralRules("en-US", {type}); + for (let start of numbers) { + for (let end of numbers) { + assertEq(pr.selectRange(start, end), "other"); + } + } + + for (let c of weirdCases) { + assertThrowsInstanceOf(() => pr.selectRange(c, 0), RangeError); + assertThrowsInstanceOf(() => pr.selectRange(0, c), RangeError); + assertThrowsInstanceOf(() => pr.selectRange(c, c), RangeError); + } + } +} + +// fr (French) returns different results. +{ + let ordinal = new Intl.PluralRules("fr", {type: "ordinal"}); + let cardinal = new Intl.PluralRules("fr", {type: "cardinal"}); + + assertEq(ordinal.selectRange(1, 1), "one"); + assertEq(ordinal.selectRange(0, 1), "other"); + + assertEq(cardinal.selectRange(1, 1), "one"); + assertEq(cardinal.selectRange(0, 1), "one"); +} + +// cy (Cymraeg) can return any combination. +{ + let ordinal = new Intl.PluralRules("cy", {type: "ordinal"}); + + assertEq(ordinal.selectRange(0, 0), "other"); + assertEq(ordinal.selectRange(0, 1), "one"); + assertEq(ordinal.selectRange(0, 2), "two"); + assertEq(ordinal.selectRange(0, 3), "few"); + assertEq(ordinal.selectRange(0, 5), "many"); + assertEq(ordinal.selectRange(0, 10), "other"); + + assertEq(ordinal.selectRange(1, 1), "other"); + assertEq(ordinal.selectRange(1, 2), "two"); + assertEq(ordinal.selectRange(1, 3), "few"); + assertEq(ordinal.selectRange(1, 5), "many"); + assertEq(ordinal.selectRange(1, 10), "other"); + + assertEq(ordinal.selectRange(2, 2), "other"); + assertEq(ordinal.selectRange(2, 3), "few"); + assertEq(ordinal.selectRange(2, 5), "many"); + assertEq(ordinal.selectRange(2, 10), "other"); + + assertEq(ordinal.selectRange(3, 3), "other"); + assertEq(ordinal.selectRange(3, 5), "many"); + assertEq(ordinal.selectRange(3, 10), "other"); + + assertEq(ordinal.selectRange(5, 5), "other"); + assertEq(ordinal.selectRange(5, 10), "other"); + + assertEq(ordinal.selectRange(10, 10), "other"); +} + +// BigInt inputs aren't allowed. +{ + let pr = new Intl.PluralRules("en-US"); + + assertThrowsInstanceOf(() => pr.selectRange(0, 0n), TypeError); + assertThrowsInstanceOf(() => pr.selectRange(0n, 0), TypeError); + assertThrowsInstanceOf(() => pr.selectRange(0n, 0n), TypeError); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/PluralRules/shell.js b/js/src/tests/non262/Intl/PluralRules/shell.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Intl/PluralRules/supportedLocalesOf.js b/js/src/tests/non262/Intl/PluralRules/supportedLocalesOf.js new file mode 100644 index 0000000000..7c6ebe8c45 --- /dev/null +++ b/js/src/tests/non262/Intl/PluralRules/supportedLocalesOf.js @@ -0,0 +1,369 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')||xulRuntime.shell) +// -- test in browser only that ICU has locale data for all Mozilla languages + +// This array contains the locales that ICU supports in +// number formatting whose languages Mozilla localizes Firefox into. +// Current as of ICU 50.1.2 and Firefox March 2013. +var locales = [ + "af", + "af-NA", + "af-ZA", + "ar", + "ar-001", + "ar-AE", + "ar-BH", + "ar-DJ", + "ar-DZ", + "ar-EG", + "ar-EH", + "ar-ER", + "ar-IL", + "ar-IQ", + "ar-JO", + "ar-KM", + "ar-KW", + "ar-LB", + "ar-LY", + "ar-MA", + "ar-MR", + "ar-OM", + "ar-PS", + "ar-QA", + "ar-SA", + "ar-SD", + "ar-SO", + "ar-SY", + "ar-TD", + "ar-TN", + "ar-YE", + "as", + "as-IN", + "be", + "be-BY", + "bg", + "bg-BG", + "bn", + "bn-BD", + "bn-IN", + "br", + "br-FR", + "bs", + "bs-Cyrl", + "bs-Cyrl-BA", + "bs-Latn", + "bs-Latn-BA", + "ca", + "ca-AD", + "ca-ES", + "cs", + "cs-CZ", + "cy", + "cy-GB", + "da", + "da-DK", + "de", + "de-AT", + "de-BE", + "de-CH", + "de-DE", + "de-LI", + "de-LU", + "el", + "el-CY", + "el-GR", + "en", + "en-150", + "en-AG", + "en-AS", + "en-AU", + "en-BB", + "en-BE", + "en-BM", + "en-BS", + "en-BW", + "en-BZ", + "en-CA", + "en-CM", + "en-DM", + "en-FJ", + "en-FM", + "en-GB", + "en-GD", + "en-GG", + "en-GH", + "en-GI", + "en-GM", + "en-GU", + "en-GY", + "en-HK", + "en-IE", + "en-IM", + "en-IN", + "en-JE", + "en-JM", + "en-KE", + "en-KI", + "en-KN", + "en-KY", + "en-LC", + "en-LR", + "en-LS", + "en-MG", + "en-MH", + "en-MP", + "en-MT", + "en-MU", + "en-MW", + "en-NA", + "en-NG", + "en-NZ", + "en-PG", + "en-PH", + "en-PK", + "en-PR", + "en-PW", + "en-SB", + "en-SC", + "en-SG", + "en-SL", + "en-SS", + "en-SZ", + "en-TC", + "en-TO", + "en-TT", + "en-TZ", + "en-UG", + "en-UM", + "en-US", + "en-US-posix", + "en-VC", + "en-VG", + "en-VI", + "en-VU", + "en-WS", + "en-ZA", + "en-ZM", + "en-ZW", + "eo", + "es", + "es-419", + "es-AR", + "es-BO", + "es-CL", + "es-CO", + "es-CR", + "es-CU", + "es-DO", + "es-EA", + "es-EC", + "es-ES", + "es-GQ", + "es-GT", + "es-HN", + "es-IC", + "es-MX", + "es-NI", + "es-PA", + "es-PE", + "es-PH", + "es-PR", + "es-PY", + "es-SV", + "es-US", + "es-UY", + "es-VE", + "et", + "et-EE", + "eu", + "eu-ES", + "fa", + "fa-AF", + "fa-IR", + "ff", + "ff-SN", + "fi", + "fi-FI", + "fr", + "fr-BE", + "fr-BF", + "fr-BI", + "fr-BJ", + "fr-BL", + "fr-CA", + "fr-CD", + "fr-CF", + "fr-CG", + "fr-CH", + "fr-CI", + "fr-CM", + "fr-DJ", + "fr-DZ", + "fr-FR", + "fr-GA", + "fr-GF", + "fr-GN", + "fr-GP", + "fr-GQ", + "fr-HT", + "fr-KM", + "fr-LU", + "fr-MA", + "fr-MC", + "fr-MF", + "fr-MG", + "fr-ML", + "fr-MQ", + "fr-MR", + "fr-MU", + "fr-NC", + "fr-NE", + "fr-PF", + "fr-RE", + "fr-RW", + "fr-SC", + "fr-SN", + "fr-SY", + "fr-TD", + "fr-TG", + "fr-TN", + "fr-VU", + "fr-YT", + "ga", + "ga-IE", + "gl", + "gl-ES", + "gu", + "gu-IN", + "he", + "he-IL", + "hi", + "hi-IN", + "hr", + "hr-BA", + "hr-HR", + "hu", + "hu-HU", + "hy", + "hy-AM", + "id", + "id-ID", + "is", + "is-IS", + "it", + "it-CH", + "it-IT", + "it-SM", + "ja", + "ja-JP", + "kk", + "kk-Cyrl", + "kk-Cyrl-KZ", + "km", + "km-KH", + "kn", + "kn-IN", + "ko", + "ko-KP", + "ko-KR", + "lt", + "lt-LT", + "lv", + "lv-LV", + "mk", + "mk-MK", + "ml", + "ml-IN", + "mr", + "mr-IN", + "nb", + "nb-NO", + "nl", + "nl-AW", + "nl-BE", + "nl-CW", + "nl-NL", + "nl-SR", + "nl-SX", + "nn", + "nn-NO", + "or", + "or-IN", + "pa", + "pa-Arab", + "pa-Arab-PK", + "pa-Guru", + "pa-Guru-IN", + "pl", + "pl-PL", + "pt", + "pt-AO", + "pt-BR", + "pt-CV", + "pt-GW", + "pt-MO", + "pt-MZ", + "pt-PT", + "pt-ST", + "pt-TL", + "rm", + "rm-CH", + "ro", + "ro-MD", + "ro-RO", + "ru", + "ru-BY", + "ru-KG", + "ru-KZ", + "ru-MD", + "ru-RU", + "ru-UA", + "si", + "si-LK", + "sk", + "sk-SK", + "sl", + "sl-SI", + "sq", + "sq-AL", + "sq-MK", + "sr", + "sr-Cyrl", + "sr-Cyrl-BA", + "sr-Cyrl-ME", + "sr-Cyrl-RS", + "sr-Latn", + "sr-Latn-BA", + "sr-Latn-ME", + "sr-Latn-RS", + "sv", + "sv-AX", + "sv-FI", + "sv-SE", + "te", + "te-IN", + "th", + "th-TH", + "tr", + "tr-CY", + "tr-TR", + "uk", + "uk-UA", + "vi", + "vi-VN", + "zh", + "zh-Hans", + "zh-Hans-CN", + "zh-Hans-HK", + "zh-Hans-MO", + "zh-Hans-SG", + "zh-Hant", + "zh-Hant-HK", + "zh-Hant-MO", + "zh-Hant-TW", +]; + +const result = Intl.PluralRules.supportedLocalesOf(locales); + +assertEqArray(locales, result); + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Intl/README.txt b/js/src/tests/non262/Intl/README.txt new file mode 100644 index 0000000000..797b49ab5c --- /dev/null +++ b/js/src/tests/non262/Intl/README.txt @@ -0,0 +1,27 @@ +Integration Tests for ECMAScript Internationalization API +========================================================= + +The tests in this directory test the integration of the ICU library +(Internationalization Components for Unicode) into the implementation of the +ECMAScript Internationalization API in SpiderMonkey. + +These integration tests are complementary to: + +- The Test402 test suite maintained by Ecma TC39, which tests conformance of + an implementation to standard ECMA-402, ECMAScript Internationalization API + Specification. Test402 is currently maintained as part of Test262, the overall + conformance test suite for ECMAScript; for more information, see + http://wiki.ecmascript.org/doku.php?id=test262:test262 + +- The test suite of the ICU library, which tests the implementation of ICU + itself and correct interpretation of the locale data it obtains from CLDR + (Common Locale Data Repository). For information on ICU, see + http://site.icu-project.org + +The integration tests check for a variety of locales and options whether the +results are localized in a way that indicates correct integration with ICU. +Such tests are somewhat fragile because the underlying locale data reflects +real world usage and is therefore subject to change. When the ICU library used +by Mozilla is upgraded, it is likely that some of the integration tests will +fail because of locale data changes; however, others might fail because of +actual software bugs. Failures therefore have to be examined carefully. diff --git a/js/src/tests/non262/Intl/RelativeTimeFormat/browser.js b/js/src/tests/non262/Intl/RelativeTimeFormat/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Intl/RelativeTimeFormat/construct-newtarget.js b/js/src/tests/non262/Intl/RelativeTimeFormat/construct-newtarget.js new file mode 100644 index 0000000000..c20c07434e --- /dev/null +++ b/js/src/tests/non262/Intl/RelativeTimeFormat/construct-newtarget.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var obj = new Intl.RelativeTimeFormat(); + +// Test that new RTF produces an object with the right prototype. +assertEq(Object.getPrototypeOf(obj), Intl.RelativeTimeFormat.prototype); + +// Test subclassing %Intl.RelativeTimeFormat% works correctly. +class MyRelativeTimeFormat extends Intl.RelativeTimeFormat {} + +var obj = new MyRelativeTimeFormat(); +assertEq(obj instanceof MyRelativeTimeFormat, true); +assertEq(obj instanceof Intl.RelativeTimeFormat, true); +assertEq(Object.getPrototypeOf(obj), MyRelativeTimeFormat.prototype); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/RelativeTimeFormat/cross-compartment.js b/js/src/tests/non262/Intl/RelativeTimeFormat/cross-compartment.js new file mode 100644 index 0000000000..c826538f39 --- /dev/null +++ b/js/src/tests/non262/Intl/RelativeTimeFormat/cross-compartment.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +var otherGlobal = newGlobal(); + +var relativeTimeFormat = new Intl.RelativeTimeFormat(); +var ccwRelativeTimeFormat = new otherGlobal.Intl.RelativeTimeFormat(); + +// Test Intl.RelativeTimeFormat.prototype.format with a CCW object. +var Intl_RelativeTimeFormat_format = Intl.RelativeTimeFormat.prototype.format; + +assertEq(Intl_RelativeTimeFormat_format.call(ccwRelativeTimeFormat, 0, "hour"), + Intl_RelativeTimeFormat_format.call(relativeTimeFormat, 0, "hour")); + +// Test Intl.RelativeTimeFormat.prototype.resolvedOptions with a CCW object. +var Intl_RelativeTimeFormat_resolvedOptions = Intl.RelativeTimeFormat.prototype.resolvedOptions; + +assertEq(deepEqual(Intl_RelativeTimeFormat_resolvedOptions.call(ccwRelativeTimeFormat), + Intl_RelativeTimeFormat_resolvedOptions.call(relativeTimeFormat)), + true); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/RelativeTimeFormat/format.js b/js/src/tests/non262/Intl/RelativeTimeFormat/format.js new file mode 100644 index 0000000000..244dbb5c56 --- /dev/null +++ b/js/src/tests/non262/Intl/RelativeTimeFormat/format.js @@ -0,0 +1,145 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')) +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Tests the format function with a diverse set of locales and options. + +var rtf; + +{ + // Numeric format + rtf = new Intl.RelativeTimeFormat("en-US"); + assertEq(rtf.format(0, "second"), "in 0 seconds"); + assertEq(rtf.format(-0, "second"), "0 seconds ago"); + assertEq(rtf.format(-1, "second"), "1 second ago"); + assertEq(rtf.format(1, "second"), "in 1 second"); + + assertEq(rtf.format(0, "minute"), "in 0 minutes"); + assertEq(rtf.format(-0, "minute"), "0 minutes ago"); + assertEq(rtf.format(-1, "minute"), "1 minute ago"); + assertEq(rtf.format(1, "minute"), "in 1 minute"); + + assertEq(rtf.format(0, "hour"), "in 0 hours"); + assertEq(rtf.format(-0, "hour"), "0 hours ago"); + assertEq(rtf.format(-1, "hour"), "1 hour ago"); + assertEq(rtf.format(1, "hour"), "in 1 hour"); + + assertEq(rtf.format(0, "day"), "in 0 days"); + assertEq(rtf.format(-0, "day"), "0 days ago"); + assertEq(rtf.format(-1, "day"), "1 day ago"); + assertEq(rtf.format(1, "day"), "in 1 day"); + + assertEq(rtf.format(0, "week"), "in 0 weeks"); + assertEq(rtf.format(-0, "week"), "0 weeks ago"); + assertEq(rtf.format(-1, "week"), "1 week ago"); + assertEq(rtf.format(1, "week"), "in 1 week"); + + assertEq(rtf.format(0, "month"), "in 0 months"); + assertEq(rtf.format(-0, "month"), "0 months ago"); + assertEq(rtf.format(-1, "month"), "1 month ago"); + assertEq(rtf.format(1, "month"), "in 1 month"); + + assertEq(rtf.format(0, "year"), "in 0 years"); + assertEq(rtf.format(-0, "year"), "0 years ago"); + assertEq(rtf.format(-1, "year"), "1 year ago"); + assertEq(rtf.format(1, "year"), "in 1 year"); +} + +{ + // Text format + rtf = new Intl.RelativeTimeFormat("en-US", { + numeric: "auto" + }); + assertEq(rtf.format(0, "second"), "now"); + assertEq(rtf.format(-0, "second"), "now"); + assertEq(rtf.format(-1, "second"), "1 second ago"); + assertEq(rtf.format(1, "second"), "in 1 second"); + + assertEq(rtf.format(0, "minute"), "this minute"); + assertEq(rtf.format(-0, "minute"), "this minute"); + assertEq(rtf.format(-1, "minute"), "1 minute ago"); + assertEq(rtf.format(1, "minute"), "in 1 minute"); + + assertEq(rtf.format(0, "hour"), "this hour"); + assertEq(rtf.format(-0, "hour"), "this hour"); + assertEq(rtf.format(-1, "hour"), "1 hour ago"); + assertEq(rtf.format(1, "hour"), "in 1 hour"); + + assertEq(rtf.format(0, "day"), "today"); + assertEq(rtf.format(-0, "day"), "today"); + assertEq(rtf.format(-1, "day"), "yesterday"); + assertEq(rtf.format(1, "day"), "tomorrow"); + + assertEq(rtf.format(0, "week"), "this week"); + assertEq(rtf.format(-0, "week"), "this week"); + assertEq(rtf.format(-1, "week"), "last week"); + assertEq(rtf.format(1, "week"), "next week"); + + assertEq(rtf.format(0, "month"), "this month"); + assertEq(rtf.format(-0, "month"), "this month"); + assertEq(rtf.format(-1, "month"), "last month"); + assertEq(rtf.format(1, "month"), "next month"); + + assertEq(rtf.format(0, "year"), "this year"); + assertEq(rtf.format(-0, "year"), "this year"); + assertEq(rtf.format(-1, "year"), "last year"); + assertEq(rtf.format(1, "year"), "next year"); +} + +{ + // Plural specifier + rtf = new Intl.RelativeTimeFormat("en-US"); + assertEq(rtf.format(1, "seconds"), "in 1 second"); + assertEq(rtf.format(1, "minutes"), "in 1 minute"); + assertEq(rtf.format(1, "hours"), "in 1 hour"); + assertEq(rtf.format(1, "days"), "in 1 day"); + assertEq(rtf.format(1, "weeks"), "in 1 week"); + assertEq(rtf.format(1, "months"), "in 1 month"); + assertEq(rtf.format(1, "years"), "in 1 year"); +} + +rtf = new Intl.RelativeTimeFormat("de", {numeric: "auto"}); +assertEq(rtf.format(-1, "day"), "gestern"); +assertEq(rtf.format(1, "day"), "morgen"); + +rtf = new Intl.RelativeTimeFormat("ar", {numeric: "auto"}); +assertEq(rtf.format(-1, "day"), "أمس"); +assertEq(rtf.format(1, "day"), "غدًا"); + + +rtf = new Intl.RelativeTimeFormat("en-US"); + +var weirdValueCases = [ + Infinity, + -Infinity, + NaN, + "word", + [0,2], + {}, +]; + +for (let c of weirdValueCases) { + assertThrowsInstanceOf(() => rtf.format(c, "year"), RangeError); +}; + +var weirdUnitCases = [ + "test", + "SECOND", + "sEcOnD", + 1, + NaN, + undefined, + null, + {}, +]; + +for (let u of weirdUnitCases) { + assertThrowsInstanceOf(function() { + var rtf = new Intl.RelativeTimeFormat("en-US"); + rtf.format(1, u); + }, RangeError); +}; + + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Intl/RelativeTimeFormat/locale-fallback-handling.js b/js/src/tests/non262/Intl/RelativeTimeFormat/locale-fallback-handling.js new file mode 100644 index 0000000000..76917c6fa0 --- /dev/null +++ b/js/src/tests/non262/Intl/RelativeTimeFormat/locale-fallback-handling.js @@ -0,0 +1,15 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// In locales that don't have a relative-date/time formatter -- and presently +// "ak" is such a locale -- behavior is expected to fall back to the root-locale +// formatter. This test verifies such fallback works as long as "ak" satisfies +// these properties; "ak" may safely be changed to a different locale if that +// ever changes. See bug 1504656. +assertEq(new Intl.RelativeTimeFormat("ak").format(1, "second"), + "+1 s"); + +if (typeof reportCompare === "function") + reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Intl/RelativeTimeFormat/numbering-system.js b/js/src/tests/non262/Intl/RelativeTimeFormat/numbering-system.js new file mode 100644 index 0000000000..d9a860bb01 --- /dev/null +++ b/js/src/tests/non262/Intl/RelativeTimeFormat/numbering-system.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Ensure passing the default numbering system leads to the same result as when +// no explicit numbering system is present. +// +// This is a regression test for the ICU issue reported at +// . + +for (var requestedLocale of [undefined, "en", "de", "fr"]) { + var rtf = new Intl.RelativeTimeFormat(requestedLocale); + var {locale, numberingSystem} = rtf.resolvedOptions(); + var rtfNu = new Intl.RelativeTimeFormat(`${locale}-u-nu-${numberingSystem}`); + + for (var unit of ["year", "quarter", "month", "week", "day", "hour", "minute", "second"]) { + for (var value of [-10, -3, -2, -1, 0, 1, 2, 3, 10]) { + assertEq(rtfNu.format(value, unit), rtf.format(value, unit)); + } + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/RelativeTimeFormat/numberingSystem-option.js b/js/src/tests/non262/Intl/RelativeTimeFormat/numberingSystem-option.js new file mode 100644 index 0000000000..bbde290dfa --- /dev/null +++ b/js/src/tests/non262/Intl/RelativeTimeFormat/numberingSystem-option.js @@ -0,0 +1,60 @@ +const defaultLocale = "en"; +const defaultNumberingSystem = new Intl.RelativeTimeFormat(defaultLocale).resolvedOptions().numberingSystem; + +function createWithLocale(locale, numberingSystem) { + return new Intl.RelativeTimeFormat(locale, {numberingSystem}); +} + +function create(numberingSystem) { + return createWithLocale(defaultLocale, numberingSystem); +} + +// Empty string should throw. +assertThrowsInstanceOf(() => create(""), RangeError); + +// Trailing \0 should throw. +assertThrowsInstanceOf(() => create("latn\0"), RangeError); + +// Too short or too long strings should throw. +assertThrowsInstanceOf(() => create("a"), RangeError); +assertThrowsInstanceOf(() => create("toolongstring"), RangeError); + +// Throw even when prefix is valid. +assertThrowsInstanceOf(() => create("latn-toolongstring"), RangeError); + +// |numberingSystem| can be set to |undefined|. +let nf = create(undefined); +assertEq(nf.resolvedOptions().numberingSystem, defaultNumberingSystem); + +// Unsupported numbering systems are ignored. +nf = create("xxxxxxxx"); +assertEq(nf.resolvedOptions().numberingSystem, defaultNumberingSystem); + +// Numbering system in options overwrite Unicode extension keyword. +nf = createWithLocale(`${defaultLocale}-u-nu-thai`, "arab"); +assertEq(nf.resolvedOptions().locale, defaultLocale); +assertEq(nf.resolvedOptions().numberingSystem, "arab"); + +// |numberingSystem| option ignores case. +nf = create("ARAB"); +assertEq(nf.resolvedOptions().locale, defaultLocale); +assertEq(nf.resolvedOptions().numberingSystem, "arab"); + +for (let [numberingSystem, {algorithmic}] of Object.entries(numberingSystems)) { + let nf1 = new Intl.RelativeTimeFormat(`${defaultLocale}-u-nu-${numberingSystem}`); + let nf2 = new Intl.RelativeTimeFormat(defaultLocale, {numberingSystem}); + + if (!algorithmic) { + assertEq(nf1.resolvedOptions().numberingSystem, numberingSystem); + assertEq(nf2.resolvedOptions().numberingSystem, numberingSystem); + } else { + // We don't yet support algorithmic numbering systems. + assertEq(nf1.resolvedOptions().numberingSystem, defaultNumberingSystem); + assertEq(nf2.resolvedOptions().numberingSystem, defaultNumberingSystem); + } + + assertEq(nf2.format(0, "second"), nf1.format(0, "second")); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/RelativeTimeFormat/relativetimeformat.js b/js/src/tests/non262/Intl/RelativeTimeFormat/relativetimeformat.js new file mode 100644 index 0000000000..fb30e5a9ce --- /dev/null +++ b/js/src/tests/non262/Intl/RelativeTimeFormat/relativetimeformat.js @@ -0,0 +1,15 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Tests the format function with a diverse set of locales and options. + +var rtf; + +rtf = new Intl.RelativeTimeFormat("en-us"); +assertEq(rtf.resolvedOptions().locale, "en-US"); +assertEq(rtf.resolvedOptions().style, "long"); +assertEq(rtf.resolvedOptions().numeric, "always"); + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Intl/RelativeTimeFormat/shell.js b/js/src/tests/non262/Intl/RelativeTimeFormat/shell.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Intl/RelativeTimeFormat/supportedLocalesOf.js b/js/src/tests/non262/Intl/RelativeTimeFormat/supportedLocalesOf.js new file mode 100644 index 0000000000..214b12570e --- /dev/null +++ b/js/src/tests/non262/Intl/RelativeTimeFormat/supportedLocalesOf.js @@ -0,0 +1,373 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')||xulRuntime.shell) +// -- test in browser only that ICU has locale data for all Mozilla languages + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// This array contains the locales that ICU supports in +// number formatting whose languages Mozilla localizes Firefox into. +// Current as of ICU 50.1.2 and Firefox March 2013. +var locales = [ + "af", + "af-NA", + "af-ZA", + "ar", + "ar-001", + "ar-AE", + "ar-BH", + "ar-DJ", + "ar-DZ", + "ar-EG", + "ar-EH", + "ar-ER", + "ar-IL", + "ar-IQ", + "ar-JO", + "ar-KM", + "ar-KW", + "ar-LB", + "ar-LY", + "ar-MA", + "ar-MR", + "ar-OM", + "ar-PS", + "ar-QA", + "ar-SA", + "ar-SD", + "ar-SO", + "ar-SY", + "ar-TD", + "ar-TN", + "ar-YE", + "as", + "as-IN", + "be", + "be-BY", + "bg", + "bg-BG", + "bn", + "bn-BD", + "bn-IN", + "br", + "br-FR", + "bs", + "bs-Cyrl", + "bs-Cyrl-BA", + "bs-Latn", + "bs-Latn-BA", + "ca", + "ca-AD", + "ca-ES", + "cs", + "cs-CZ", + "cy", + "cy-GB", + "da", + "da-DK", + "de", + "de-AT", + "de-BE", + "de-CH", + "de-DE", + "de-LI", + "de-LU", + "el", + "el-CY", + "el-GR", + "en", + "en-150", + "en-AG", + "en-AS", + "en-AU", + "en-BB", + "en-BE", + "en-BM", + "en-BS", + "en-BW", + "en-BZ", + "en-CA", + "en-CM", + "en-DM", + "en-FJ", + "en-FM", + "en-GB", + "en-GD", + "en-GG", + "en-GH", + "en-GI", + "en-GM", + "en-GU", + "en-GY", + "en-HK", + "en-IE", + "en-IM", + "en-IN", + "en-JE", + "en-JM", + "en-KE", + "en-KI", + "en-KN", + "en-KY", + "en-LC", + "en-LR", + "en-LS", + "en-MG", + "en-MH", + "en-MP", + "en-MT", + "en-MU", + "en-MW", + "en-NA", + "en-NG", + "en-NZ", + "en-PG", + "en-PH", + "en-PK", + "en-PR", + "en-PW", + "en-SB", + "en-SC", + "en-SG", + "en-SL", + "en-SS", + "en-SZ", + "en-TC", + "en-TO", + "en-TT", + "en-TZ", + "en-UG", + "en-UM", + "en-US", + "en-US-posix", + "en-VC", + "en-VG", + "en-VI", + "en-VU", + "en-WS", + "en-ZA", + "en-ZM", + "en-ZW", + "eo", + "es", + "es-419", + "es-AR", + "es-BO", + "es-CL", + "es-CO", + "es-CR", + "es-CU", + "es-DO", + "es-EA", + "es-EC", + "es-ES", + "es-GQ", + "es-GT", + "es-HN", + "es-IC", + "es-MX", + "es-NI", + "es-PA", + "es-PE", + "es-PH", + "es-PR", + "es-PY", + "es-SV", + "es-US", + "es-UY", + "es-VE", + "et", + "et-EE", + "eu", + "eu-ES", + "fa", + "fa-AF", + "fa-IR", + "ff", + "ff-SN", + "fi", + "fi-FI", + "fr", + "fr-BE", + "fr-BF", + "fr-BI", + "fr-BJ", + "fr-BL", + "fr-CA", + "fr-CD", + "fr-CF", + "fr-CG", + "fr-CH", + "fr-CI", + "fr-CM", + "fr-DJ", + "fr-DZ", + "fr-FR", + "fr-GA", + "fr-GF", + "fr-GN", + "fr-GP", + "fr-GQ", + "fr-HT", + "fr-KM", + "fr-LU", + "fr-MA", + "fr-MC", + "fr-MF", + "fr-MG", + "fr-ML", + "fr-MQ", + "fr-MR", + "fr-MU", + "fr-NC", + "fr-NE", + "fr-PF", + "fr-RE", + "fr-RW", + "fr-SC", + "fr-SN", + "fr-SY", + "fr-TD", + "fr-TG", + "fr-TN", + "fr-VU", + "fr-YT", + "ga", + "ga-IE", + "gl", + "gl-ES", + "gu", + "gu-IN", + "he", + "he-IL", + "hi", + "hi-IN", + "hr", + "hr-BA", + "hr-HR", + "hu", + "hu-HU", + "hy", + "hy-AM", + "id", + "id-ID", + "is", + "is-IS", + "it", + "it-CH", + "it-IT", + "it-SM", + "ja", + "ja-JP", + "kk", + "kk-Cyrl", + "kk-Cyrl-KZ", + "km", + "km-KH", + "kn", + "kn-IN", + "ko", + "ko-KP", + "ko-KR", + "lt", + "lt-LT", + "lv", + "lv-LV", + "mk", + "mk-MK", + "ml", + "ml-IN", + "mr", + "mr-IN", + "nb", + "nb-NO", + "nl", + "nl-AW", + "nl-BE", + "nl-CW", + "nl-NL", + "nl-SR", + "nl-SX", + "nn", + "nn-NO", + "or", + "or-IN", + "pa", + "pa-Arab", + "pa-Arab-PK", + "pa-Guru", + "pa-Guru-IN", + "pl", + "pl-PL", + "pt", + "pt-AO", + "pt-BR", + "pt-CV", + "pt-GW", + "pt-MO", + "pt-MZ", + "pt-PT", + "pt-ST", + "pt-TL", + "rm", + "rm-CH", + "ro", + "ro-MD", + "ro-RO", + "ru", + "ru-BY", + "ru-KG", + "ru-KZ", + "ru-MD", + "ru-RU", + "ru-UA", + "si", + "si-LK", + "sk", + "sk-SK", + "sl", + "sl-SI", + "sq", + "sq-AL", + "sq-MK", + "sr", + "sr-Cyrl", + "sr-Cyrl-BA", + "sr-Cyrl-ME", + "sr-Cyrl-RS", + "sr-Latn", + "sr-Latn-BA", + "sr-Latn-ME", + "sr-Latn-RS", + "sv", + "sv-AX", + "sv-FI", + "sv-SE", + "te", + "te-IN", + "th", + "th-TH", + "tr", + "tr-CY", + "tr-TR", + "uk", + "uk-UA", + "vi", + "vi-VN", + "zh", + "zh-Hans", + "zh-Hans-CN", + "zh-Hans-HK", + "zh-Hans-MO", + "zh-Hans-SG", + "zh-Hant", + "zh-Hant-HK", + "zh-Hant-MO", + "zh-Hant-TW", +]; + +const result = Intl.RelativeTimeFormat.supportedLocalesOf(locales); + +assertEqArray(locales, result); + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Intl/Segmenter/browser.js b/js/src/tests/non262/Intl/Segmenter/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Intl/Segmenter/cross-compartment.js b/js/src/tests/non262/Intl/Segmenter/cross-compartment.js new file mode 100644 index 0000000000..58845e6b62 --- /dev/null +++ b/js/src/tests/non262/Intl/Segmenter/cross-compartment.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')||!this.Intl.Segmenter) + +var g = newGlobal({}); + +var segmenter = new Intl.Segmenter(); +var ccwSegmenter = new g.Intl.Segmenter(); + +const SegmentsPrototype = Object.getPrototypeOf(segmenter.segment("")); +const SegmentIteratorPrototype = Object.getPrototypeOf(segmenter.segment("")[Symbol.iterator]()); + +// Intl.Segmenter.prototype.resolvedOptions () +var resolved1 = Intl.Segmenter.prototype.resolvedOptions.call(segmenter); +var resolved2 = Intl.Segmenter.prototype.resolvedOptions.call(ccwSegmenter); +assertDeepEq(resolved1, resolved2); + +// Intl.Segmenter.prototype.segment +var seg1 = Intl.Segmenter.prototype.segment.call(segmenter, "This is a test."); +var seg2 = Intl.Segmenter.prototype.segment.call(ccwSegmenter, "This is a test."); + +// %Segments.prototype%.containing ( index ) +var data1 = SegmentsPrototype.containing.call(seg1, 10); +var data2 = SegmentsPrototype.containing.call(seg2, 10); +assertDeepEq(data1, data2); + +// %Segments.prototype% [ @@iterator ] () +var iter1 = SegmentsPrototype[Symbol.iterator].call(seg1); +var iter2 = SegmentsPrototype[Symbol.iterator].call(seg2); + +// %SegmentIterator.prototype%.next () +var result1 = SegmentIteratorPrototype.next.call(iter1); +var result2 = SegmentIteratorPrototype.next.call(iter2); +assertDeepEq(result1, result2); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/Segmenter/grapheme-latin1.js b/js/src/tests/non262/Intl/Segmenter/grapheme-latin1.js new file mode 100644 index 0000000000..3b54c02236 --- /dev/null +++ b/js/src/tests/non262/Intl/Segmenter/grapheme-latin1.js @@ -0,0 +1,37 @@ +// |reftest| slow skip-if(!this.hasOwnProperty('Intl')||!this.Intl.Segmenter) + +// CRLF should be the only compound grapheme for Latin-1 strings. + +let segmenter = new Intl.Segmenter("en", {granularity: "grapheme"}); + +for (let i = 0; i <= 0xff; ++i) { + for (let j = 0; j <= 0xff; ++j) { + let string = String.fromCodePoint(i, j); + let segments = segmenter.segment(string); + + let data1 = segments.containing(0); + let data2 = segments.containing(1); + let graphemes = [...segments]; + + if (i === "\r".charCodeAt(0) && j === "\n".charCodeAt(0)) { + assertEq(data1.index, 0); + assertEq(data1.segment, "\r\n"); + + assertEq(data2.index, 0); + assertEq(data2.segment, "\r\n"); + + assertEq(graphemes.length, 1); + } else { + assertEq(data1.index, 0); + assertEq(data1.segment, String.fromCodePoint(i)); + + assertEq(data2.index, 1); + assertEq(data2.segment, String.fromCodePoint(j)); + + assertEq(graphemes.length, 2); + } + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/Segmenter/grapheme.js b/js/src/tests/non262/Intl/Segmenter/grapheme.js new file mode 100644 index 0000000000..c51de7f8d0 --- /dev/null +++ b/js/src/tests/non262/Intl/Segmenter/grapheme.js @@ -0,0 +1,110 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')||!this.Intl.Segmenter) + +// Grapheme boundaries are locale independent. Test with various locales to +// ensure we get the same results. +const locales = [ + "en", "de", "fr", "ar", "ja", "zh", "th", +]; + +let strings = { + // Empty string + "": [], + + // Ascii + "test": "test".split(""), + "hello world": "hello world".split(""), + "hello\0world": "hello\0world".split(""), + "\r\n": ["\r\n"], + + // Latin-1 + "äöü éèê µß \xff": "äöü éèê µß \xff".split(""), + + // Two-Byte + "中文字": "中文字".split(""), + + // Grapheme Clusters: https://www.unicode.org/reports/tr29/#Table_Sample_Grapheme_Clusters + "e\u0300": ["e\u0300"], + "\u1100\u1161\u11A8": ["\u1100\u1161\u11A8"], // Hangul syllable "gag" + "\u0E01\u0E33": ["\u0E01\u0E33"], // Thai kam + "\u0937\u093F": ["\u0937\u093F"], // Devanagari ssi + + // Emojis + "\u263A\uFE0F": ["\u263A\uFE0F"], // Variant selector + "\u{1F385}\u{1F3FB}": ["\u{1F385}\u{1F3FB}"], // Skin tone selector + "\u{1F469}\u{1F3FD}\u{200D}\u{1F52C}": ["\u{1F469}\u{1F3FD}\u{200D}\u{1F52C}"], // ZWJ + "\u{1F469}\u{1F3FD}\u{200D}\u{1F52C}\u{FE0F}": ["\u{1F469}\u{1F3FD}\u{200D}\u{1F52C}\u{FE0F}"], // ZWJ + VS + "\u{1F926}\u{1F3FC}\u{200D}\u{2642}\u{FE0F}": ["\u{1F926}\u{1F3FC}\u{200D}\u{2642}\u{FE0F}"], // ZWJ + VS with BMP modifier + "\u{1F1E9}\u{1F1EA}": ["\u{1F1E9}\u{1F1EA}"], // Flags + "\u{1F3F4}\u{E0067}\u{E0062}\u{E0073}\u{E0063}\u{E0074}\u{E007F}": ["\u{1F3F4}\u{E0067}\u{E0062}\u{E0073}\u{E0063}\u{E0074}\u{E007F}"], // Subdivision flags +}; + +function assertIsSegmentDataObject(obj) { + // The prototype is %Object.prototype%. + assertEq(Object.getPrototypeOf(obj), Object.prototype); + + // The Segment Data object has exactly three own properties. + let keys = Reflect.ownKeys(obj); + assertEq(keys.length, 3); + assertEq(keys[0], "segment"); + assertEq(keys[1], "index"); + assertEq(keys[2], "input"); + + // Ensure each property has the correct value type. + assertEq(typeof obj.segment, "string"); + assertEq(typeof obj.index, "number"); + assertEq(typeof obj.input, "string"); + + // |index| is an integer index into |string|. + assertEq(Number.isInteger(obj.index), true); + assertEq(obj.index >= 0, true); + assertEq(obj.index < obj.input.length, true); + + // Segments are non-empty. + assertEq(obj.segment.length > 0, true); + + // Ensure the segment is present in the input at the correct position. + assertEq(obj.input.substr(obj.index, obj.segment.length), obj.segment); +} + +function segmentsFromContaining(segmenter, string) { + let segments = segmenter.segment(string); + + let result = []; + for (let index = 0, data; (data = segments.containing(index)); index += data.segment.length) { + result.push(data); + } + return result; +} + +for (let locale of locales) { + let segmenter = new Intl.Segmenter(locale, {granularity: "grapheme"}); + + let resolved = segmenter.resolvedOptions(); + assertEq(resolved.locale, locale); + assertEq(resolved.granularity, "grapheme"); + + for (let [string, graphemes] of Object.entries(strings)) { + let segments = [...segmenter.segment(string)]; + + // Assert each segment is a valid Segment Data object. + segments.forEach(assertIsSegmentDataObject); + + // Concatenating all segments should return the input. + assertEq(segments.reduce((acc, {segment}) => acc + segment, ""), string); + + // The "input" property matches the original input string. + assertEq(segments.every(({input}) => input === string), true); + + // The indices are sorted in ascending order. + assertEq(isNaN(segments.reduce((acc, {index}) => index > acc ? index : NaN, -Infinity)), false); + + // The computed segments match the expected value. + assertEqArray(segments.map(({segment}) => segment), graphemes); + + // Segment iteration and %Segments.prototype%.containing return the same results. + assertDeepEq(segmentsFromContaining(segmenter, string), segments); + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/Segmenter/refresh-text-asan.js b/js/src/tests/non262/Intl/Segmenter/refresh-text-asan.js new file mode 100644 index 0000000000..98ad7c56f5 --- /dev/null +++ b/js/src/tests/non262/Intl/Segmenter/refresh-text-asan.js @@ -0,0 +1,15 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')||!this.Intl.Segmenter) + +// Test fails in ASan builds when ubrk_refreshUText isn't called. + +let string = "A. "; + +let segmenter = new Intl.Segmenter(undefined, {granularity: "sentence"}); +let segments = segmenter.segment(string.repeat(100)); + +for (let {segment} of segments) { + assertEq(segment, string); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/Segmenter/sentence-latin.js b/js/src/tests/non262/Intl/Segmenter/sentence-latin.js new file mode 100644 index 0000000000..cebb029a40 --- /dev/null +++ b/js/src/tests/non262/Intl/Segmenter/sentence-latin.js @@ -0,0 +1,96 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')||!this.Intl.Segmenter) + +// https://www.unicode.org/reports/tr29/#Sentence_Boundary_Rules + +const strings = { + // SB1, SB2 + "": [], + + // SB3 + "\r\n": ["\r\n"], + + // SB4 + "First paragraph.\nSecond paragraph.": ["First paragraph.\n", "Second paragraph."], + "First paragraph.\rSecond paragraph.": ["First paragraph.\r", "Second paragraph."], + "First paragraph.\r\nSecond paragraph.": ["First paragraph.\r\n", "Second paragraph."], + "First paragraph.\x85Second paragraph.": ["First paragraph.\x85", "Second paragraph."], + + // SB5 + "\xADWo\xADrd\xAD.\xAD": ["\xADWo\xADrd\xAD.\xAD"], + "Word.\n\xAD": ["Word.\n", "\xAD"], + "Word.\r\xAD\n": ["Word.\r", "\xAD\n"], + + // SB6 + ".2": [".2"], + "1.2": ["1.2"], + "!2": ["!", "2"], + "1!2": ["1!", "2"], + + // SB7 + "A.B": ["A.B"], + "a.B": ["a.B"], + "A. B": ["A. ", "B"], + "a. B": ["a. ", "B"], + + // SB8 + "#.a": ["#.a"], + "#. a": ["#. a"], + "#. # a": ["#. # a"], + "#. 1 a": ["#. 1 a"], + "#. , a": ["#. , a"], + "#. Aa": ["#. ", "Aa"], + + // SB8a + "Word..": ["Word.."], + "Word . , ": ["Word . , "], + "Word.'\t , ": ["Word.'\t , "], + + // SB9, SB10, SB11 + "Word.''": ["Word.''"], + "Word.'\t ": ["Word.'\t "], + "Word.'\t \n": ["Word.'\t \n"], +}; + +function assertSegments(string, sentences) { + let seg = segmenter.segment(string); + let segments = [...seg]; + + // The computed segments match the expected value. + assertEqArray(segments.map(({segment}) => segment), sentences); + + // |containing()| should return the same result. + for (let expected of segments) { + let {segment, index} = expected; + for (let i = index; i < index + segment.length; ++i) { + let actual = seg.containing(i); + assertDeepEq(actual, expected); + } + } +} + +let segmenter = new Intl.Segmenter("en", {granularity: "sentence"}); + +for (let [string, words] of Object.entries(strings)) { + assertSegments(string, words); +} + +// Locale-dependent sentence segmentation. +{ + // https://en.wikipedia.org/wiki/Greek_question_mark#Greek_question_mark + let string = "A sentence; semicolon separated."; + + let english = new Intl.Segmenter("en", {granularity: "sentence"}); + let greek = new Intl.Segmenter("el", {granularity: "sentence"}); + + // A single sentence in English. + assertEq([...english.segment(string)].length, 1); + + // ICU4C: Two sentences in Greek. + // assertEq([...greek.segment(string)].length, 2); + + // ICU4X: A single sentence in Greek. + assertEq([...greek.segment(string)].length, 1); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/Segmenter/sentence.js b/js/src/tests/non262/Intl/Segmenter/sentence.js new file mode 100644 index 0000000000..326d6f1b86 --- /dev/null +++ b/js/src/tests/non262/Intl/Segmenter/sentence.js @@ -0,0 +1,137 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')||!this.Intl.Segmenter) + +// Sentence boundaries can be locale dependent. The following locales don't use +// any custom tailoring, so they should give the same results. +const locales = [ + "en", "de", "fr", "ar", "ja", "zh", "th", +]; + +let strings = { + // Empty string + "": [], + + // Ascii + "This is an English sentence. And this is another one.": [ + "This is an English sentence. ", + "And this is another one." + ], + "The colon: it doesn't start a new sentence.": [ + "The colon: it doesn't start a new sentence." + ], + + // Latin-1 + "Unnötig umständlich Wörter überlegen. Und dann lästigerweise zu längeren Sätzen überarbeiten!": [ + "Unnötig umständlich Wörter überlegen. ", + "Und dann lästigerweise zu längeren Sätzen überarbeiten!" + ], + + // Two-Byte + // Source: https://ja.wikipedia.org/wiki/Unicode + "Unicode(ユニコード)は、符号化文字集合や文字符号化方式などを定めた、文字コードの業界規格。文字集合(文字セット)が単一の大規模文字セットであること(「Uni」という名はそれに由来する)などが特徴である。": [ + "Unicode(ユニコード)は、符号化文字集合や文字符号化方式などを定めた、文字コードの業界規格。", + "文字集合(文字セット)が単一の大規模文字セットであること(「Uni」という名はそれに由来する)などが特徴である。" + ], +}; + +function assertIsSegmentDataObject(obj) { + // The prototype is %Object.prototype%. + assertEq(Object.getPrototypeOf(obj), Object.prototype); + + // The Segment Data object has exactly three own properties. + let keys = Reflect.ownKeys(obj); + assertEq(keys.length, 3); + assertEq(keys[0], "segment"); + assertEq(keys[1], "index"); + assertEq(keys[2], "input"); + + // Ensure each property has the correct value type. + assertEq(typeof obj.segment, "string"); + assertEq(typeof obj.index, "number"); + assertEq(typeof obj.input, "string"); + + // |index| is an integer index into |string|. + assertEq(Number.isInteger(obj.index), true); + assertEq(obj.index >= 0, true); + assertEq(obj.index < obj.input.length, true); + + // Segments are non-empty. + assertEq(obj.segment.length > 0, true); + + // Ensure the segment is present in the input at the correct position. + assertEq(obj.input.substr(obj.index, obj.segment.length), obj.segment); +} + +function segmentsFromContaining(segmenter, string) { + let segments = segmenter.segment(string); + + let result = []; + for (let index = 0, data; (data = segments.containing(index)); index += data.segment.length) { + result.push(data); + } + return result; +} + +for (let locale of locales) { + let segmenter = new Intl.Segmenter(locale, {granularity: "sentence"}); + + let resolved = segmenter.resolvedOptions(); + assertEq(resolved.locale, locale); + assertEq(resolved.granularity, "sentence"); + + for (let [string, sentences] of Object.entries(strings)) { + let segments = [...segmenter.segment(string)]; + + // Assert each segment is a valid Segment Data object. + segments.forEach(assertIsSegmentDataObject); + + // Concatenating all segments should return the input. + assertEq(segments.reduce((acc, {segment}) => acc + segment, ""), string); + + // The "input" property matches the original input string. + assertEq(segments.every(({input}) => input === string), true); + + // The indices are sorted in ascending order. + assertEq(isNaN(segments.reduce((acc, {index}) => index > acc ? index : NaN, -Infinity)), false); + + // The computed segments match the expected value. + assertEqArray(segments.map(({segment}) => segment), sentences); + + // Segment iteration and %Segments.prototype%.containing return the same results. + assertDeepEq(segmentsFromContaining(segmenter, string), segments); + } +} + +// Sentence break suppressions through the "ss" Unicode extension key aren't supported. +{ + let segmenter = new Intl.Segmenter("en-u-ss-standard", {granularity: "sentence"}); + assertEq(segmenter.resolvedOptions().locale, "en"); + + let segments = [...segmenter.segment("Dr. Strange is a fictional character.")]; + assertEqArray(segments.map(({segment}) => segment), + ["Dr. ", "Strange is a fictional character."]); +} + +// Locale-dependent sentence segmentation. +{ + // https://en.wikipedia.org/wiki/Greek_question_mark#Greek_question_mark + let string1 = "Από πού είσαι; Τί κάνεις;"; + let string2 = string1.replaceAll(";", "\u037E"); // U+037E GREEK QUESTION MARK + assertEq(string1 !== string2, true); + + for (let string of [string1, string2]) { + let english = new Intl.Segmenter("en", {granularity: "sentence"}); + let greek = new Intl.Segmenter("el", {granularity: "sentence"}); + + // A single sentence in English. + assertEq([...english.segment(string)].length, 1); + + // But two sentences in Greek. + // + // ICU4X doesn't support locale-specific tailoring: + // https://github.com/unicode-org/icu4x/issues/3284 + // assertEq([...greek.segment(string)].length, 2); + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/Segmenter/shell.js b/js/src/tests/non262/Intl/Segmenter/shell.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Intl/Segmenter/surrogate-pair-split.js b/js/src/tests/non262/Intl/Segmenter/surrogate-pair-split.js new file mode 100644 index 0000000000..e7c9fcf727 --- /dev/null +++ b/js/src/tests/non262/Intl/Segmenter/surrogate-pair-split.js @@ -0,0 +1,57 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')||!this.Intl.Segmenter) + +// Calling %Segments.prototype%.containing in the middle of a surrogate pair +// doubles back to the lead surrogate. + +// Grapheme +{ + let segmenter = new Intl.Segmenter(undefined, {granularity: "grapheme"}); + + let string = "\u{1F925}"; + let segments = segmenter.segment(string); + + let data1 = segments.containing(0); + let data2 = segments.containing(1); + let data3 = segments.containing(2); + + assertEq(data1.segment, string); + assertDeepEq(data1, data2); + assertEq(data3, undefined); +} + +// Word +{ + let segmenter = new Intl.Segmenter(undefined, {granularity: "word"}); + + let prefix = "Nothing to see here! "; + let string = "\u{1F925}"; + let segments = segmenter.segment(prefix + string); + + let data1 = segments.containing(prefix.length + 0); + let data2 = segments.containing(prefix.length + 1); + let data3 = segments.containing(prefix.length + 2); + + assertEq(data1.segment, string); + assertDeepEq(data1, data2); + assertEq(data3, undefined); +} + +// Sentence +{ + let segmenter = new Intl.Segmenter(undefined, {granularity: "sentence"}); + + let prefix = "Nothing to see here! Please disperse. "; + let string = "\u{1F925}"; + let segments = segmenter.segment(prefix + string); + + let data1 = segments.containing(prefix.length + 0); + let data2 = segments.containing(prefix.length + 1); + let data3 = segments.containing(prefix.length + 2); + + assertEq(data1.segment, string); + assertDeepEq(data1, data2); + assertEq(data3, undefined); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/Segmenter/word-latin1.js b/js/src/tests/non262/Intl/Segmenter/word-latin1.js new file mode 100644 index 0000000000..396947cc1c --- /dev/null +++ b/js/src/tests/non262/Intl/Segmenter/word-latin1.js @@ -0,0 +1,215 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')||!this.Intl.Segmenter) + +// https://www.unicode.org/reports/tr29/#Word_Boundary_Rules + +const strings = { + // WB1, WB2 + "": [], + + // WB3 + "\r\n": ["\r\n"], + + // WB3a, WB3b + "\n": ["\n"], + "\r": ["\r"], + "\v": ["\v"], + "\f": ["\f"], + "\x85": ["\x85"], + + // WB3d + " ": [" "], + " ": [" "], + + // WB4 + "\xAD": ["\xAD"], + "\xAD\xAD": ["\xAD\xAD"], + + // WB5 + "a": ["a"], + "ab": ["ab"], + + // WB6, WB7 + "a:b": ["a:b"], + "a·b": ["a·b"], + "a.b": ["a.b"], + "a'b": ["a'b"], + + // WB8 + "1": ["1"], + "12": ["12"], + + // WB9 + "a1": ["a1"], + + // WB10 + "1a": ["1a"], + + // WB11, WB12 + "1,2": ["1,2"], + "1;2": ["1;2"], + "1.2": ["1.2"], + "1'2": ["1'2"], + + // WB13a + "a_": ["a_"], + "1_": ["1_"], + "__": ["__"], + + // WB13b + "_a": ["_a"], + "_1": ["_1"], + + // WB999 + "\0": ["\0"], + "?": ["?"], + "??": ["?", "?"], +}; + +function assertSegments(string, words) { + let seg = segmenter.segment(string); + let segments = [...seg]; + + // The computed segments match the expected value. + assertEqArray(segments.map(({segment}) => segment), words); + + // |containing()| should return the same result. + for (let expected of segments) { + let {segment, index} = expected; + for (let i = index; i < index + segment.length; ++i) { + let actual = seg.containing(i); + assertDeepEq(actual, expected); + } + } +} + +let segmenter = new Intl.Segmenter("en", {granularity: "word"}); + +for (let [string, words] of Object.entries(strings)) { + assertSegments(string, words); +} + +// WB3, WB3a, WB3b and WB4 +for (let string of ["\r\n", "\n", "\r", "\v", "\f", "\x85"]) { + assertSegments(string + "\xAD", [string, "\xAD"]); + assertSegments("\xAD" + string, ["\xAD", string]); +} + +// WB3d and WB4 +for (let string of [" ", " "]) { + assertSegments(string + "\xAD", [string + "\xAD"]); + assertSegments("\xAD" + string, ["\xAD", string]); +} +assertSegments(" \xAD ", [" \xAD", " "]); +assertSegments(" \xAD\xAD ", [" \xAD\xAD", " "]); + +// WB5-WB13 and WB4 +for (let string of [ + // WB5 + "a", "ab", + + // WB6, WB7 + "a:b", + "a·b", + "a.b", + "a'b", + + // WB8 + "1", + "12", + + // WB9 + "a1", + + // WB10 + "1a", + + // WB11, WB12 + "1,2", + "1;2", + "1.2", + "1'2", + + // WB13a + "a_", + "1_", + "__", + + // WB13b + "_a", + "_1", + + // WB999 + "?", +]) { + assertSegments(string + "\xAD", [string + "\xAD"]); + assertSegments("\xAD" + string, ["\xAD", string]); + + if (string === "a.b") { + // ICU4X incorrectly splits the result into three words. + // https://github.com/unicode-org/icu4x/issues/4417 + assertSegments(string.split("").join("\xAD"), ["a\xAD", ".\xAD", "b"]); + assertSegments(string.split("").join("\xAD\xAD"), ["a\xAD\xAD", ".\xAD\xAD", "b"]); + } else { + assertSegments(string.split("").join("\xAD"), [string.split("").join("\xAD")]); + assertSegments(string.split("").join("\xAD\xAD"), [string.split("").join("\xAD\xAD")]); + } +} + +assertSegments("?\xAD?", ["?\xAD", "?"]); + +for (let string of [ + // WB6, WB7 + "a:b", + "a·b", + "a.b", + "a'b", + + // WB11, WB12 + "1,2", + "1;2", + "1.2", + "1'2", +]) { + let prefix = string.slice(0, -1); + let suffix = string.slice(1); + + assertSegments(prefix, prefix.split("")); + assertSegments(suffix, suffix.split("")); +} + +// MidNum with ALetter +assertSegments("a,b", ["a", ",", "b"]); +assertSegments("a;b", ["a", ";", "b"]); + +// MidLetter with Numeric +assertSegments("1:2", ["1", ":", "2"]); +assertSegments("1·2", ["1", "·", "2"]); + +// MidNumLet with mixed ALetter and Numeric +assertSegments("a.2", ["a", ".", "2"]); +assertSegments("1.b", ["1", ".", "b"]); +assertSegments("a'2", ["a", "'", "2"]); +assertSegments("1'b", ["1", "'", "b"]); + +// MidNum with ExtendNumLet +assertSegments("_,_", ["_", ",", "_"]); +assertSegments("_;_", ["_", ";", "_"]); + +// MidLetter with ExtendNumLet +assertSegments("_:_", ["_", ":", "_"]); +assertSegments("_·_", ["_", "·", "_"]); + +// MidNumLet with ExtendNumLet +assertSegments("_._", ["_", ".", "_"]); +assertSegments("_'_", ["_", "'", "_"]); + +// CLDR has locale-dependent word segmentation for the "en-posix" locale. This +// locale is currently not selectable, so the Latin-1 fast-paths don't need to +// implement it. If one of the two below assertions ever fail, please update +// the Latin-1 fast-paths for word segmentation to implement the "en-posix" +// changes. +assertEq(new Intl.Segmenter("en-posix").resolvedOptions().locale, "en"); +assertEq(new Intl.Segmenter("en-u-va-posix").resolvedOptions().locale, "en"); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/Segmenter/word.js b/js/src/tests/non262/Intl/Segmenter/word.js new file mode 100644 index 0000000000..5b3e1747a3 --- /dev/null +++ b/js/src/tests/non262/Intl/Segmenter/word.js @@ -0,0 +1,152 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')||!this.Intl.Segmenter) + +// Word boundaries are locale independent. Test with various locales to ensure +// we get the same results. +const locales = [ + "en", "de", "fr", "ar", "ja", "zh", "th", +]; + +let strings = { + // Empty string + "": [], + + // Ascii + "This is an English sentence.": [ + "This", " ", "is", " ", "an", " ", "English", " ", "sentence", "." + ], + "Moi? N'est-ce pas.": [ + "Moi", "?", " ", "N'est", "-", "ce", " ", "pas", "." + ], + + // Latin-1 + "Unnötig umständlich Wörter überlegen.": [ + "Unnötig", " ", "umständlich", " ", "Wörter", " ", "überlegen", "." + ], + + // Two-Byte + // Source: https://en.wikipedia.org/wiki/Japanese_writing_system#Examples + "ラドクリフ、マラソン五輪代表に 1万メートル出場にも含み。": [ + "ラドクリフ", "、", "マラソン", "五輪", "代表", "に", " ", "1", "万", "メートル", "出場", "に", "も", "含み", "。" + ], + + // From: Language Sense and Ambiguity in Thai + // Source: https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.98.118 + "ขนบนอก": [ + // According to the paper this should instead be separated into ขน|บน|อก. + "ขนบ", "นอก" + ], + "พนักงานนําโคลงเรือสามตัว": [ + // Expected segmentation is พนักงาน|นํา|โค|ลง|เรือ|สาม|ตัว. + + // ICU4C segmentation: + // "พนัก", "งาน", "นํา", "โคลง", "เรือ", "สาม", "ตัว" + + // ICU4X segmentation: + "พ", "นัก", "งานนํา", "โคลง", "เรือ", "สาม", "ตัว" + ], + + "หมอหุงขาวสวยด": [ + // Has three possible segmentations: + // หมอหงขาว|สวย|ด + // หมอ|หง|ขาวสวย|ด + // หมอ|หง|ขาว|สวย|ด + + // ICU4C segmentation: + // "หมอ", "หุง", "ขาว", "สวย", "ด" + + // ICU4X segmentation: + "หมอ", "หุง", "ขาว", "สวยด" + ], + + // From: Thoughts on Word and Sentence Segmentation in Thai + // Source: https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.63.7038 + "หนังสือรวมบทความทางวิชาการในการประชุมสัมมนา": [ + "หนังสือ", "รวม", "บทความ", "ทาง", "วิชาการ", "ใน", "การ", "ประชุม", "สัมมนา" + ], +}; + +function assertIsSegmentDataObject(obj) { + // The prototype is %Object.prototype%. + assertEq(Object.getPrototypeOf(obj), Object.prototype); + + // The Segment Data object has exactly four own properties. + let keys = Reflect.ownKeys(obj); + assertEq(keys.length, 4); + assertEq(keys[0], "segment"); + assertEq(keys[1], "index"); + assertEq(keys[2], "input"); + assertEq(keys[3], "isWordLike"); + + // Ensure each property has the correct value type. + assertEq(typeof obj.segment, "string"); + assertEq(typeof obj.index, "number"); + assertEq(typeof obj.input, "string"); + assertEq(typeof obj.isWordLike, "boolean"); + + // |index| is an integer index into |string|. + assertEq(Number.isInteger(obj.index), true); + assertEq(obj.index >= 0, true); + assertEq(obj.index < obj.input.length, true); + + // Segments are non-empty. + assertEq(obj.segment.length > 0, true); + + // Ensure the segment is present in the input at the correct position. + assertEq(obj.input.substr(obj.index, obj.segment.length), obj.segment); + + // The non-word parts in the samples are either punctuators or space separators. + let expectedWordLike = !/^(\p{gc=P}|\p{gc=Zs})+$/u.test(obj.segment); + + // ICU4X incorrectly marks the last segment as non-word like for Thai. + // https://github.com/unicode-org/icu4x/issues/4446 + let isThai = /^\p{sc=Thai}+$/u.test(obj.segment); + let isLastSegment = obj.index + obj.segment.length === obj.input.length; + if (isThai && isLastSegment) { + expectedWordLike = false; + } + + assertEq(obj.isWordLike, expectedWordLike, obj.segment); +} + +function segmentsFromContaining(segmenter, string) { + let segments = segmenter.segment(string); + + let result = []; + for (let index = 0, data; (data = segments.containing(index)); index += data.segment.length) { + result.push(data); + } + return result; +} + +for (let locale of locales) { + let segmenter = new Intl.Segmenter(locale, {granularity: "word"}); + + let resolved = segmenter.resolvedOptions(); + assertEq(resolved.locale, locale); + assertEq(resolved.granularity, "word"); + + for (let [string, words] of Object.entries(strings)) { + let segments = [...segmenter.segment(string)]; + + // Assert each segment is a valid Segment Data object. + segments.forEach(assertIsSegmentDataObject); + + // Concatenating all segments should return the input. + assertEq(segments.reduce((acc, {segment}) => acc + segment, ""), string); + + // The "input" property matches the original input string. + assertEq(segments.every(({input}) => input === string), true); + + // The indices are sorted in ascending order. + assertEq(isNaN(segments.reduce((acc, {index}) => index > acc ? index : NaN, -Infinity)), false); + + // The computed segments match the expected value. + assertEqArray(segments.map(({segment}) => segment), words); + + // Segment iteration and %Segments.prototype%.containing return the same results. + assertDeepEq(segmentsFromContaining(segmenter, string), segments); + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/String/shell.js b/js/src/tests/non262/Intl/String/shell.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Intl/String/toLocaleLowerCase.js b/js/src/tests/non262/Intl/String/toLocaleLowerCase.js new file mode 100644 index 0000000000..bd81717d22 --- /dev/null +++ b/js/src/tests/non262/Intl/String/toLocaleLowerCase.js @@ -0,0 +1,64 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Test language dependent special casing with different language tags. +for (let locale of ["tr", "TR", "tr-TR", "tr-u-co-search", "tr-x-turkish"]) { + assertEq("\u0130".toLocaleLowerCase(locale), "i"); + assertEq("\u0130".toLocaleLowerCase([locale]), "i"); + + // Additional language tags are ignored. + assertEq("\u0130".toLocaleLowerCase([locale, "und"]), "i"); + assertEq("\u0130".toLocaleLowerCase(["und", locale]), "\u0069\u0307"); +} + +// Ensure "trl" (Traveller Scottish) isn't misrecognized as "tr", even though +// both share the same prefix. +assertEq("\u0130".toLocaleLowerCase("trl"), "\u0069\u0307"); +assertEq("\u0130".toLocaleLowerCase(["trl"]), "\u0069\u0307"); + +// Language tag is always verified. +for (let locale of ["no_locale", "tr-invalid_ext", ["no_locale"], ["en", "no_locale"]]) { + // Empty input string. + assertThrowsInstanceOf(() => "".toLocaleLowerCase(locale), RangeError); + + // Non-empty input string. + assertThrowsInstanceOf(() => "x".toLocaleLowerCase(locale), RangeError); +} + +// No locale argument, undefined as locale, and empty array or array-like all +// return the same result. Testing with "a/A" because it has only simple case +// mappings. +assertEq("A".toLocaleLowerCase(), "a"); +assertEq("A".toLocaleLowerCase(undefined), "a"); +assertEq("A".toLocaleLowerCase([]), "a"); +assertEq("A".toLocaleLowerCase({}), "a"); +assertEq("A".toLocaleLowerCase({length: 0}), "a"); +assertEq("A".toLocaleLowerCase({length: -1}), "a"); + +// Test with incorrect locale type. +for (let locale of [null, 0, Math.PI, NaN, Infinity, true, false, Symbol()]) { + // Empty input string. + assertThrowsInstanceOf(() => "".toLocaleLowerCase([locale]), TypeError); + + // Non-empty input string. + assertThrowsInstanceOf(() => "A".toLocaleLowerCase([locale]), TypeError); +} + +// Primitives are converted with ToObject and then queried for .length property. +for (let locale of [null]) { + // Empty input string. + assertThrowsInstanceOf(() => "".toLocaleLowerCase([locale]), TypeError); + + // Non-empty input string. + assertThrowsInstanceOf(() => "A".toLocaleLowerCase([locale]), TypeError); +} +// ToLength(ToObject()) returns 0. +for (let locale of [0, Math.PI, NaN, Infinity, true, false, Symbol()]) { + // Empty input string. + assertEq("".toLocaleLowerCase(locale), ""); + + // Non-empty input string. + assertEq("A".toLocaleLowerCase(locale), "a"); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/String/toLocaleUpperCase.js b/js/src/tests/non262/Intl/String/toLocaleUpperCase.js new file mode 100644 index 0000000000..0a33320dc7 --- /dev/null +++ b/js/src/tests/non262/Intl/String/toLocaleUpperCase.js @@ -0,0 +1,64 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Test language dependent special casing with different language tags. +for (let locale of ["lt", "LT", "lt-LT", "lt-u-co-phonebk", "lt-x-lietuva"]) { + assertEq("i\u0307".toLocaleUpperCase(locale), "I"); + assertEq("i\u0307".toLocaleUpperCase([locale]), "I"); + + // Additional language tags are ignored. + assertEq("i\u0307".toLocaleUpperCase([locale, "und"]), "I"); + assertEq("i\u0307".toLocaleUpperCase(["und", locale]), "I\u0307"); +} + +// Ensure "lti" (Leti) isn't misrecognized as "lt", even though both share the +// same prefix. +assertEq("i\u0307".toLocaleUpperCase("lti"), "I\u0307"); +assertEq("i\u0307".toLocaleUpperCase(["lti"]), "I\u0307"); + +// Language tag is always verified. +for (let locale of ["no_locale", "lt-invalid_ext", ["no_locale"], ["en", "no_locale"]]) { + // Empty input string. + assertThrowsInstanceOf(() => "".toLocaleUpperCase(locale), RangeError); + + // Non-empty input string. + assertThrowsInstanceOf(() => "a".toLocaleUpperCase(locale), RangeError); +} + +// No locale argument, undefined as locale, and empty array or array-like all +// return the same result. Testing with "a/A" because it has only simple case +// mappings. +assertEq("a".toLocaleUpperCase(), "A"); +assertEq("a".toLocaleUpperCase(undefined), "A"); +assertEq("a".toLocaleUpperCase([]), "A"); +assertEq("a".toLocaleUpperCase({}), "A"); +assertEq("a".toLocaleUpperCase({length: 0}), "A"); +assertEq("a".toLocaleUpperCase({length: -1}), "A"); + +// Test with incorrect locale type. +for (let locale of [null, 0, Math.PI, NaN, Infinity, true, false, Symbol()]) { + // Empty input string. + assertThrowsInstanceOf(() => "".toLocaleUpperCase([locale]), TypeError); + + // Non-empty input string. + assertThrowsInstanceOf(() => "a".toLocaleUpperCase([locale]), TypeError); +} + +// Primitives are converted with ToObject and then queried for .length property. +for (let locale of [null]) { + // Empty input string. + assertThrowsInstanceOf(() => "".toLocaleUpperCase([locale]), TypeError); + + // Non-empty input string. + assertThrowsInstanceOf(() => "a".toLocaleUpperCase([locale]), TypeError); +} +// ToLength(ToObject()) returns 0. +for (let locale of [0, Math.PI, NaN, Infinity, true, false, Symbol()]) { + // Empty input string. + assertEq("".toLocaleUpperCase(locale), ""); + + // Non-empty input string. + assertEq("a".toLocaleUpperCase(locale), "A"); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Intl/TypedArray/shell.js b/js/src/tests/non262/Intl/TypedArray/shell.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Intl/TypedArray/toLocaleString.js b/js/src/tests/non262/Intl/TypedArray/toLocaleString.js new file mode 100644 index 0000000000..7a5d0be30a --- /dev/null +++ b/js/src/tests/non262/Intl/TypedArray/toLocaleString.js @@ -0,0 +1,103 @@ +if (typeof Intl === "object") { + const constructors = [ + Int8Array, + Uint8Array, + Uint8ClampedArray, + Int16Array, + Uint16Array, + Int32Array, + Uint32Array, + Float32Array, + Float64Array, + ]; + + const localeSep = [,,].toLocaleString(); + + const originalNumberToLocaleString = Number.prototype.toLocaleString; + + // Missing arguments are passed as |undefined|. + for (let constructor of constructors) { + Number.prototype.toLocaleString = function() { + assertEq(arguments.length, 2); + assertEq(arguments[0], undefined); + assertEq(arguments[1], undefined); + return "pass"; + }; + + // Single element case. + assertEq(new constructor(1).toLocaleString(), "pass"); + + // More than one element. + assertEq(new constructor(2).toLocaleString(), "pass" + localeSep + "pass"); + } + Number.prototype.toLocaleString = originalNumberToLocaleString; + + // Missing options is passed as |undefined|. + for (let constructor of constructors) { + Number.prototype.toLocaleString = function() { + assertEq(arguments.length, 2); + assertEq(arguments[0], locales); + assertEq(arguments[1], undefined); + return "pass"; + }; + let locales = {}; + + // Single element case. + assertEq(new constructor(1).toLocaleString(locales), "pass"); + + // More than one element. + assertEq(new constructor(2).toLocaleString(locales), "pass" + localeSep + "pass"); + } + Number.prototype.toLocaleString = originalNumberToLocaleString; + + // Ensure "locales" and "options" arguments are passed to the array elements. + for (let constructor of constructors) { + Number.prototype.toLocaleString = function() { + assertEq(arguments.length, 2); + assertEq(arguments[0], locales); + assertEq(arguments[1], options); + return "pass"; + }; + let locales = {}; + let options = {}; + + // Single element case. + assertEq(new constructor(1).toLocaleString(locales, options), "pass"); + + // More than one element. + assertEq(new constructor(2).toLocaleString(locales, options), "pass" + localeSep + "pass"); + } + Number.prototype.toLocaleString = originalNumberToLocaleString; + + assertEq(new Float32Array([NaN]).toLocaleString("ar"), "ليس رقم"); + assertEq(new Float64Array([NaN]).toLocaleString(["zh-hant", "ar"]), "非數值"); + assertEq(new Float32Array([Infinity]).toLocaleString(["dz"]), "གྲངས་མེད"); + assertEq(new Float64Array([-Infinity]).toLocaleString(["fr", "en"]), "-∞"); + + const sampleValues = [-0, +0, -1, +1, -2, +2, -0.5, +0.5]; + const sampleLocales = [ + void 0, + "en", + "th-th-u-nu-thai", + ["tlh", "de"], + ]; + const sampleOptions = [ + void 0, + {}, + {style: "percent"}, + {style: "currency", currency: "USD", minimumIntegerDigits: 4}, + ]; + for (let locale of sampleLocales) { + for (let options of sampleOptions) { + let nf = new Intl.NumberFormat(locale, options); + for (let constructor of constructors) { + let typedArray = new constructor(sampleValues); + let expected = [].map.call(typedArray, nf.format).join(localeSep); + assertEq(typedArray.toLocaleString(locale, options), expected); + } + } + } +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/available-locales-implied-script.js b/js/src/tests/non262/Intl/available-locales-implied-script.js new file mode 100644 index 0000000000..d9abbebf49 --- /dev/null +++ b/js/src/tests/non262/Intl/available-locales-implied-script.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')) + +if (typeof getAvailableLocalesOf === "undefined") { + var getAvailableLocalesOf = SpecialPowers.Cu.getJSTestingFunctions().getAvailableLocalesOf; +} + +function IsIntlService(c) { + return typeof c === "function" && + c.hasOwnProperty("prototype") && + c.prototype.hasOwnProperty("resolvedOptions"); +} + +const intlConstructors = Object.getOwnPropertyNames(Intl).map(name => Intl[name]).filter(IsIntlService); + +// Test all Intl service constructors. +for (let intlConstructor of intlConstructors) { + // Retrieve all available locales of the given Intl service constructor. + let available = getAvailableLocalesOf(intlConstructor.name); + let availableSet = new Set(available); + + available.filter(x => { + return new Intl.Locale(x); + }).filter(loc => { + // Find all locales which have both a script and a region subtag. + return loc.script && loc.region; + }).forEach(loc => { + let noScript = `${loc.language}-${loc.region}`; + + // The locale without a script subtag must also be available. + assertEq(availableSet.has(noScript), true, `Missing locale ${noScript} for ${loc}`); + }); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/available-locales-resolved.js b/js/src/tests/non262/Intl/available-locales-resolved.js new file mode 100644 index 0000000000..76b144d275 --- /dev/null +++ b/js/src/tests/non262/Intl/available-locales-resolved.js @@ -0,0 +1,41 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')) + +if (typeof getAvailableLocalesOf === "undefined") { + var getAvailableLocalesOf = SpecialPowers.Cu.getJSTestingFunctions().getAvailableLocalesOf; +} + +function IsIntlService(c) { + return typeof c === "function" && + c.hasOwnProperty("prototype") && + c.prototype.hasOwnProperty("resolvedOptions"); +} + +const intlConstructors = Object.getOwnPropertyNames(Intl).map(name => Intl[name]).filter(IsIntlService); + +// Test all Intl service constructors. +for (let intlConstructor of intlConstructors) { + // Retrieve all available locales of the given Intl service constructor. + let available = getAvailableLocalesOf(intlConstructor.name); + + // "best fit" matchers could potentially return a different locale, so we only + // test with "lookup" locale matchers. (NB: We don't yet support "best fit" + // matchers.) + let options = {localeMatcher: "lookup"}; + + if (intlConstructor === Intl.DisplayNames) { + // Intl.DisplayNames can't be constructed without the "type" option. + options.type = "language"; + } + + for (let locale of available) { + let obj = new intlConstructor(locale, options); + let resolved = obj.resolvedOptions(); + + // If |locale| is an available locale, the "lookup" locale matcher should + // pick exactly that locale. + assertEq(resolved.locale, locale); + } +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/available-locales-supported.js b/js/src/tests/non262/Intl/available-locales-supported.js new file mode 100644 index 0000000000..d11b5d714f --- /dev/null +++ b/js/src/tests/non262/Intl/available-locales-supported.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')) + +if (typeof getAvailableLocalesOf === "undefined") { + var getAvailableLocalesOf = SpecialPowers.Cu.getJSTestingFunctions().getAvailableLocalesOf; +} + +function IsIntlService(c) { + return typeof c === "function" && + c.hasOwnProperty("prototype") && + c.prototype.hasOwnProperty("resolvedOptions"); +} + +const intlConstructors = Object.getOwnPropertyNames(Intl).map(name => Intl[name]).filter(IsIntlService); + +// Test all Intl service constructors. +for (let intlConstructor of intlConstructors) { + // Retrieve all available locales of the given Intl service constructor. + let available = getAvailableLocalesOf(intlConstructor.name); + + // All available locales must be reported as supported. + let supported = intlConstructor.supportedLocalesOf(available); + assertEqArray(supported, available); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/best-available-locale-from-default-locale.js b/js/src/tests/non262/Intl/best-available-locale-from-default-locale.js new file mode 100644 index 0000000000..16a0e0348f --- /dev/null +++ b/js/src/tests/non262/Intl/best-available-locale-from-default-locale.js @@ -0,0 +1,107 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')) + +if (typeof getDefaultLocale === "undefined") { + var getDefaultLocale = SpecialPowers.Cu.getJSTestingFunctions().getDefaultLocale; +} +if (typeof setDefaultLocale === "undefined") { + var setDefaultLocale = SpecialPowers.Cu.getJSTestingFunctions().setDefaultLocale; +} + +let defaultLocale = null; + +function withLocale(locale, fn) { + if (defaultLocale === null) + defaultLocale = getDefaultLocale(); + + setDefaultLocale(locale); + try { + fn(); + } finally { + setDefaultLocale(defaultLocale); + } +} + +// This test assumes Azerbaijani ("az") is a supported locale. +const supported = Intl.Collator.supportedLocalesOf("az"); +assertEq(supported.length, 1); +assertEq(supported[0], "az"); + +withLocale("az", () => { + // Ensure the new default locale is now active. + assertEq(new Intl.Collator().resolvedOptions().locale, "az"); + + // "az" is the active default locale, so explicitly requesting "az" should succeed. + assertEq(new Intl.Collator("az").resolvedOptions().locale, "az"); + + // ICU doesn't provide a specialised "az-Cyrl" locale, so we fallback to "az". + assertEq(new Intl.Collator("az-Cyrl").resolvedOptions().locale, "az"); + + // ICU doesn't provide a specialised "az-Cyrl-AZ" locale, so we fallback to "az". + assertEq(new Intl.Collator("az-Cyrl-AZ").resolvedOptions().locale, "az"); +}); + +// As demonstrated above, "az-Cyrl-AZ" normally isn't a supported Intl.Collator locale. But when +// used as the default locale, it gets promoted to being supported, because its parent locale "az" +// is supported and can act as a fallback. +// +// This works as follows: +// We accept any default locale as long as it can be supported either explicitly or implicitly +// through a fallback. But when we claim a default locale is supported, we also need to make sure +// we report any parent locale as being supported. So when "az-Cyrl-AZ" is accepted as the +// default locale, we also need to report its parent locale "az-Cyrl" as a supported locale. +// +// The reason we're doing this, is to make sure we aren't limiting the supported default locale to +// the intersection of the sets of supported locales for each Intl service constructor. Also see +// the requirements in , which state that the default +// locale must be a member of [[AvailableLocales]] for every Intl service constructor. +// +// So the following statement must hold: +// +// ∀ Constructor ∈ IntlConstructors: DefaultLocale ∈ Constructor.[[AvailableLocales]] +// +// This can trivially be achieved when we restrict the default locale to: +// +// { RequestedLocale if RequestedLocale ∈ (∩ C.[[AvailableLocales]]) +// { C ∈ IntlConstructors +// { +// DefaultLocale = { Fallback(RequestedLocale) if Fallback(RequestedLocale) ∈ (∩ C.[[AvailableLocales]]) +// { C ∈ IntlConstructors +// { +// { LastDitchLocale otherwise +// +// But that severely restricts the possible default locales. For example, "az-Cyrl-AZ" is supported +// by all Intl constructors except Intl.Collator. Intl.Collator itself only provides explicit +// support for the parent locale "az". So with the trivial solution we'd need to mark "az-Cyrl-AZ" +// as an invalid default locale and instead use its fallback locale "az". +// +// So instead of that we're using the following approach: +// +// { RequestedLocale if RequestedLocale ∈ (∩ C.[[AvailableLocales]]) +// { C ∈ IntlConstructors +// { +// DefaultLocale = { RequestedLocale if Fallback(RequestedLocale) ∈ (∩ C.[[AvailableLocales]]) +// { C ∈ IntlConstructors +// { +// { LastDitchLocale otherwise +// +// So even when the requested default locale is only implicitly supported through a fallback, we +// still accept it as a valid default locale. +withLocale("az-Cyrl-AZ", () => { + // Ensure the new default locale is now active. + assertEq(new Intl.Collator().resolvedOptions().locale, "az-Cyrl-AZ"); + + // "az-Cyrl-AZ" is the active default locale, so explicitly requesting the parent locale + // "az" should succeed. + assertEq(new Intl.Collator("az").resolvedOptions().locale, "az"); + + // "az-Cyrl-AZ" is the active default locale, so explicitly requesting the parent locale + // "az-Cyrl" should succeed. + assertEq(new Intl.Collator("az-Cyrl").resolvedOptions().locale, "az-Cyrl"); + + // "az-Cyrl-AZ" is the active default locale, so explicitly requesting "az-Cyrl-AZ" + // should succeed. + assertEq(new Intl.Collator("az-Cyrl-AZ").resolvedOptions().locale, "az-Cyrl-AZ"); +}); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/browser.js b/js/src/tests/non262/Intl/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Intl/default-locale-shell.js b/js/src/tests/non262/Intl/default-locale-shell.js new file mode 100644 index 0000000000..ea3f6d17db --- /dev/null +++ b/js/src/tests/non262/Intl/default-locale-shell.js @@ -0,0 +1,16 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")||!xulRuntime.shell) + +// js/src/tests/lib/tests.py sets the default locale to "en-US" for shell tests. +// Ensure it's correctly set in the runtime and for the Intl service constructors. +const defaultLocale = "en-US"; + +assertEq(getDefaultLocale(), defaultLocale); + +assertEq(new Intl.Collator().resolvedOptions().locale, defaultLocale); +assertEq(new Intl.DateTimeFormat().resolvedOptions().locale, defaultLocale); +assertEq(new Intl.NumberFormat().resolvedOptions().locale, defaultLocale); +assertEq(new Intl.PluralRules().resolvedOptions().locale, defaultLocale); +assertEq(new Intl.RelativeTimeFormat().resolvedOptions().locale, defaultLocale); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/duplicate-variants.js b/js/src/tests/non262/Intl/duplicate-variants.js new file mode 100644 index 0000000000..5d07a9b109 --- /dev/null +++ b/js/src/tests/non262/Intl/duplicate-variants.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// RFC 5646 section 2.1 +// variant = 5*8alphanum ; registered variants +// / (DIGIT 3alphanum) + +// Duplicate variants are forbidden. +assertEqArray(Intl.getCanonicalLocales("de-1996"), ["de-1996"]); +assertThrowsInstanceOf(() => Intl.getCanonicalLocales("de-1996-1996"), RangeError); + +// Multiple different variants are allowed. +assertEqArray(Intl.getCanonicalLocales("sl-rozaj-solba"), ["sl-rozaj-solba"]); + +// Variants can have the same prefix. +assertEqArray(Intl.getCanonicalLocales("zh-Latn-pinyin-pinyin2"), ["zh-Latn-pinyin-pinyin2"]); + +// Values in extension sequences are not counted as variants. +assertEqArray(Intl.getCanonicalLocales("en-u-kf-false-kn-false"), ["en-u-kf-false-kn-false"]); + +// Also test duplicates in Unicode extension keywords and attributes. +// From https://tools.ietf.org/html/rfc6067#section-2.1 +// +// An 'attribute' is a subtag with a length of three to eight +// characters following the singleton and preceding any 'keyword' +// sequences. No attributes were defined at the time of this +// document's publication. +// +// A 'keyword' is a sequence of subtags consisting of a 'key' subtag, +// followed by zero or more 'type' subtags (so a 'key' might appear +// alone and not be accompanied by a 'type' subtag). A 'key' MUST +// NOT appear more than once in a language tag's extension string. +// +// ... +// +// Only the first occurrence of an attribute or key conveys meaning in a +// language tag. When interpreting tags containing the Unicode locale +// extension, duplicate attributes or keywords are ignored in the +// following way: ignore any attribute that has already appeared in the +// tag and ignore any keyword whose key has already occurred in the tag. +// +// The duplicates itself are removed in CanonicalizeUnicodeLocaleId, step 2-3. +assertEqArray(Intl.getCanonicalLocales("en-u-kn-false-kn-false"), ["en-u-kn-false"]); +assertEqArray(Intl.getCanonicalLocales("en-u-attr1-attr2-attr2"), ["en-u-attr1-attr2"]); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/extensions/browser.js b/js/src/tests/non262/Intl/extensions/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Intl/extensions/options-value-emulates-undefined.js b/js/src/tests/non262/Intl/extensions/options-value-emulates-undefined.js new file mode 100644 index 0000000000..5b2ee124aa --- /dev/null +++ b/js/src/tests/non262/Intl/extensions/options-value-emulates-undefined.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!xulRuntime.shell||!this.hasOwnProperty('Intl')) +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 843004; +var summary = + "Use of an object that emulates |undefined| as the sole option must " + + "preclude imputing default values"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var opt = createIsHTMLDDA(); +opt.toString = function() { return "long"; }; + +var str = new Date(2013, 12 - 1, 14).toLocaleString("en-US", { weekday: opt }); + +// Because "weekday" was present and not undefined (stringifying to "long"), +// this must be a string like "Saturday" (in this implementation, that is). +assertEq(str, "Saturday"); + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Intl/extensions/shell.js b/js/src/tests/non262/Intl/extensions/shell.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Intl/extensions/unicode-extension-sequences.js b/js/src/tests/non262/Intl/extensions/unicode-extension-sequences.js new file mode 100644 index 0000000000..ead69a4632 --- /dev/null +++ b/js/src/tests/non262/Intl/extensions/unicode-extension-sequences.js @@ -0,0 +1,74 @@ +// |reftest| skip-if(!this.getSelfHostedValue) + +const startOfUnicodeExtensions = getSelfHostedValue("startOfUnicodeExtensions"); +const endOfUnicodeExtensions = getSelfHostedValue("endOfUnicodeExtensions"); + +const testcases = [ + // Language tag without Unicode extension. + { locale: "en", start: -1, end: 0 }, + { locale: "en-Latn", start: -1, end: 0 }, + { locale: "en-x-y", start: -1, end: 0 }, + { locale: "en-x-yz", start: -1, end: 0 }, + { locale: "en-x-u-kf", start: -1, end: 0 }, + + // Unicode extension sequence starts with key subtag. + // - no suceeding key or type subtags. + { locale: "en-u-ab", start: 2, end: 7 }, + { locale: "en-u-ab-x-y", start: 2, end: 7 }, + { locale: "en-u-ab-x-yz", start: 2, end: 7 }, + { locale: "en-u-ab-x-u-kn", start: 2, end: 7 }, + // - followed by key subtag. + { locale: "en-u-ab-cd", start: 2, end: 10 }, + { locale: "en-u-ab-cd-x-y", start: 2, end: 10 }, + { locale: "en-u-ab-cd-x-yz", start: 2, end: 10 }, + { locale: "en-u-ab-cd-x-u-kn", start: 2, end: 10 }, + // - followed by type subtag. + { locale: "en-u-ab-cdef", start: 2, end: 12 }, + { locale: "en-u-ab-cdef-x-y", start: 2, end: 12 }, + { locale: "en-u-ab-cdef-x-yz", start: 2, end: 12 }, + { locale: "en-u-ab-cdef-x-y-u-kn", start: 2, end: 12 }, + + // Unicode extension sequence starts with attribute subtag. + // - no suceeding attribute or key subtags. + { locale: "en-u-abc", start: 2, end: 8 }, + { locale: "en-u-abc-x-y", start: 2, end: 8 }, + { locale: "en-u-abc-x-yz", start: 2, end: 8 }, + { locale: "en-u-abc-x-y-u-kn", start: 2, end: 8 }, + // - followed by attribute subtag. + { locale: "en-u-abc-def", start: 2, end: 12 }, + { locale: "en-u-abc-def-x-y", start: 2, end: 12 }, + { locale: "en-u-abc-def-x-yz", start: 2, end: 12 }, + { locale: "en-u-abc-def-x-y-u-kn", start: 2, end: 12 }, + // - followed by key subtag. + { locale: "en-u-abc-de", start: 2, end: 11 }, + { locale: "en-u-abc-de-x-y", start: 2, end: 11 }, + { locale: "en-u-abc-de-x-yz", start: 2, end: 11 }, + { locale: "en-u-abc-de-x-y-u-kn", start: 2, end: 11 }, + // - followed by two key subtags. + { locale: "en-u-abc-de-fg", start: 2, end: 14 }, + { locale: "en-u-abc-de-fg-x-y", start: 2, end: 14 }, + { locale: "en-u-abc-de-fg-x-yz", start: 2, end: 14 }, + { locale: "en-u-abc-de-fg-x-y-u-kn", start: 2, end: 14 }, + // - followed by key and type subtag. + { locale: "en-u-abc-de-fgh", start: 2, end: 15 }, + { locale: "en-u-abc-de-fgh-x-y", start: 2, end: 15 }, + { locale: "en-u-abc-de-fgh-x-yz", start: 2, end: 15 }, + { locale: "en-u-abc-de-fgh-x-y-u-kn", start: 2, end: 15 }, + + // Also test when the Unicode extension doesn't start at index 2. + { locale: "en-Latn-u-kf", start: 7, end: 12 }, + { locale: "und-u-kf", start: 3, end: 8 }, +]; + +for (const {locale, start, end} of testcases) { + // Ensure the input is a valid language tag. + assertEqArray(Intl.getCanonicalLocales(locale), [locale]); + + assertEq(startOfUnicodeExtensions(locale), start); + + if (start >= 0) + assertEq(endOfUnicodeExtensions(locale, start), end); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/fallback-symbol.js b/js/src/tests/non262/Intl/fallback-symbol.js new file mode 100644 index 0000000000..87943257ce --- /dev/null +++ b/js/src/tests/non262/Intl/fallback-symbol.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Intl')) + +function IntlFallbackSymbol(constructor) { + return Object.getOwnPropertySymbols(constructor.call(Object.create(constructor.prototype)))[0]; +} + +const dateTimeFormatIntlFallbackSymbol = IntlFallbackSymbol(Intl.DateTimeFormat); +const numberFormatIntlFallbackSymbol = IntlFallbackSymbol(Intl.NumberFormat); + +// Intl.DateTimeFormat and Intl.NumberFormat both use the same fallback symbol. +assertEq(dateTimeFormatIntlFallbackSymbol, numberFormatIntlFallbackSymbol); + +const intlFallbackSymbol = dateTimeFormatIntlFallbackSymbol; + +// The fallback symbol is a Symbol value. +assertEq(typeof intlFallbackSymbol, "symbol"); + +// Test the description of the fallback symbol. +assertEq(Symbol.prototype.toString.call(intlFallbackSymbol), "Symbol(IntlLegacyConstructedSymbol)"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/four-letter-language-codes.js b/js/src/tests/non262/Intl/four-letter-language-codes.js new file mode 100644 index 0000000000..394efacf29 --- /dev/null +++ b/js/src/tests/non262/Intl/four-letter-language-codes.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Four letter language subtags are not allowed. +const languageTags = [ + "root", // Special meaning in Unicode CLDR locale identifiers. + "Latn", // Unicode CLDR locale identifiers can start with a script subtag. + "Flob", // And now some non-sense input. + "ZORK", + "Blah-latn", + "QuuX-latn-us", + "SPAM-gb-x-Sausages-BACON-eggs", +]; + +for (let tag of languageTags) { + assertThrowsInstanceOf(() => Intl.getCanonicalLocales(tag), RangeError); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/getCalendarInfo.js b/js/src/tests/non262/Intl/getCalendarInfo.js new file mode 100644 index 0000000000..5c9a8e24da --- /dev/null +++ b/js/src/tests/non262/Intl/getCalendarInfo.js @@ -0,0 +1,76 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")||!this.hasOwnProperty("addIntlExtras")) +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Tests the getCalendarInfo function with a diverse set of arguments. + +function checkCalendarInfo(info, expected) +{ + assertEq(Object.getPrototypeOf(info), Object.prototype); + + assertEq(info.firstDayOfWeek, expected.firstDayOfWeek); + assertEq(info.minDays, expected.minDays); + assertDeepEq(info.weekend, expected.weekend); + assertEq(info.calendar, expected.calendar); + assertEq(info.locale, expected.locale); +} + +addIntlExtras(Intl); + +let gCI = Intl.getCalendarInfo; + +assertEq(gCI.length, 1); + +checkCalendarInfo(gCI('en-US'), { + firstDayOfWeek: 7, + minDays: 1, + weekend: [6, 7], + calendar: "gregory", + locale: "en-US" +}); + +checkCalendarInfo(gCI('en-IL'), { + firstDayOfWeek: 7, + minDays: 1, + weekend: [5, 6], + calendar: "gregory", + locale: "en-IL" +}); + + +checkCalendarInfo(gCI('en-GB'), { + firstDayOfWeek: 1, + minDays: 4, + weekend: [6, 7], + calendar: "gregory", + locale: "en-GB" +}); + + +checkCalendarInfo(gCI('pl'), { + firstDayOfWeek: 1, + minDays: 4, + weekend: [6, 7], + calendar: "gregory", + locale: "pl" +}); + +checkCalendarInfo(gCI('ar-IQ'), { + firstDayOfWeek: 6, + minDays: 1, + weekend: [5, 6], + calendar: "gregory", + locale: "ar-IQ" +}); + +checkCalendarInfo(gCI('fa-IR'), { + firstDayOfWeek: 6, + minDays: 1, + weekend: [5], + calendar: "persian", + locale: "fa-IR" +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/getCanonicalLocales-overridden-arg-length.js b/js/src/tests/non262/Intl/getCanonicalLocales-overridden-arg-length.js new file mode 100644 index 0000000000..f0cb3d4ee3 --- /dev/null +++ b/js/src/tests/non262/Intl/getCanonicalLocales-overridden-arg-length.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Tests the getCanonicalLocales function for overridden argument's length. + +var count = 0; +var locs = { get length() { if (count++ > 0) throw 42; return 0; } }; +var locales = Intl.getCanonicalLocales(locs); // shouldn't throw 42 +assertEq(locales.length, 0); + + +var obj = { get 0() { throw new Error("must not be gotten!"); }, + length: -Math.pow(2, 32) + 1 }; + +assertEq(Intl.getCanonicalLocales(obj).length, 0); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/getCanonicalLocales-overridden-push.js b/js/src/tests/non262/Intl/getCanonicalLocales-overridden-push.js new file mode 100644 index 0000000000..36f53ebf06 --- /dev/null +++ b/js/src/tests/non262/Intl/getCanonicalLocales-overridden-push.js @@ -0,0 +1,16 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Tests the getCanonicalLocales function for overriden Array.push. + +Array.prototype.push = () => { throw 42; }; + +// must not throw 42, might if push is used +var arr = Intl.getCanonicalLocales(["en-US"]); + +assertEqArray(arr, ["en-US"]); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/getCanonicalLocales-overridden-set.js b/js/src/tests/non262/Intl/getCanonicalLocales-overridden-set.js new file mode 100644 index 0000000000..396f3a9483 --- /dev/null +++ b/js/src/tests/non262/Intl/getCanonicalLocales-overridden-set.js @@ -0,0 +1,16 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Tests the getCanonicalLocales function for overridden set(). + +Object.defineProperty(Array.prototype, 0, { set() { throw 42; } }); + +// must not throw 42, might if push is used +var arr = Intl.getCanonicalLocales(["en-US"]); + +assertEqArray(arr, ["en-US"]); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/getCanonicalLocales-overridden-species.js b/js/src/tests/non262/Intl/getCanonicalLocales-overridden-species.js new file mode 100644 index 0000000000..858735b581 --- /dev/null +++ b/js/src/tests/non262/Intl/getCanonicalLocales-overridden-species.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Tests the getCanonicalLocales function for overriden Array[Symbol.species]. + +Object.defineProperty(Array, Symbol.species, { + value: function() { + return new Proxy(["?"], { + get(t, pk, r) { + return Reflect.get(t, pk, r); + }, + defineProperty(t, pk) { + return true; + } + }); + } +}); + +var arr = Intl.getCanonicalLocales("de-x-private"); + +assertEqArray(arr, ["de-x-private"]); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/getCanonicalLocales-weird-cases.js b/js/src/tests/non262/Intl/getCanonicalLocales-weird-cases.js new file mode 100644 index 0000000000..d67fda355f --- /dev/null +++ b/js/src/tests/non262/Intl/getCanonicalLocales-weird-cases.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Locale processing is supposed to internally remove any Unicode extension +// sequences in the locale. Test that various weird testcases invoking +// algorithmic edge cases don't assert or throw exceptions. + +var weirdCases = + [ + "en-x-u-foo", + "en-a-bar-x-u-foo", + "en-x-u-foo-a-bar", + "en-a-bar-u-baz-x-u-foo", + ]; + +for (let weird of weirdCases) + assertEqArray(Intl.getCanonicalLocales(weird), [weird]); + +assertThrowsInstanceOf(() => Intl.getCanonicalLocales("x-u-foo"), RangeError); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); + diff --git a/js/src/tests/non262/Intl/getCanonicalLocales-with-duplicates.js b/js/src/tests/non262/Intl/getCanonicalLocales-with-duplicates.js new file mode 100644 index 0000000000..c029569482 --- /dev/null +++ b/js/src/tests/non262/Intl/getCanonicalLocales-with-duplicates.js @@ -0,0 +1,15 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Tests the getCanonicalLocales function for duplicate locales scenario. + +assertEqArray(Intl.getCanonicalLocales(['ab-cd', 'ff', 'de-rt', 'ab-Cd']), + ['ab-CD', 'ff', 'de-RT']); + +var locales = Intl.getCanonicalLocales(["en-US", "en-US"]); +assertEqArray(locales, ['en-US']); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/getCanonicalLocales.js b/js/src/tests/non262/Intl/getCanonicalLocales.js new file mode 100644 index 0000000000..66e9b87c5c --- /dev/null +++ b/js/src/tests/non262/Intl/getCanonicalLocales.js @@ -0,0 +1,37 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Tests the getCanonicalLocales function with a diverse set of arguments. + +let gCL = Intl.getCanonicalLocales; + +assertEq(Intl.getCanonicalLocales.length, 1); + +assertEqArray(gCL(), []); + +assertEqArray(gCL('ab-cd'), ['ab-CD']); + +assertEqArray(gCL(['ab-cd']), ['ab-CD']); + +assertEqArray(gCL(['ab-cd', 'FF']), ['ab-CD', 'ff']); + +assertEqArray(gCL({'a': 0}), []); + +assertEqArray(gCL({}), []); + +assertEqArray(gCL(['ar-ma-u-ca-islamicc']), ['ar-MA-u-ca-islamic-civil']); + +assertEqArray(gCL(['th-th-u-nu-thai']), ['th-TH-u-nu-thai']); + +assertEqArray(gCL(NaN), []); + +assertEqArray(gCL(1), []); + +Number.prototype[0] = "en-US"; +Number.prototype.length = 1; +assertEqArray(gCL(NaN), ["en-US"]); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/legacy-and-sign-locales-with-unicode-extensions.js b/js/src/tests/non262/Intl/legacy-and-sign-locales-with-unicode-extensions.js new file mode 100644 index 0000000000..2421d9bb09 --- /dev/null +++ b/js/src/tests/non262/Intl/legacy-and-sign-locales-with-unicode-extensions.js @@ -0,0 +1,79 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const languageTags = { + // Case 1: legacy, regular tags. + "art-lojban": "jbo", + "cel-gaulish": "xtg", + "zh-guoyu": "zh", + "zh-hakka": "hak", + "zh-xiang": "hsn", + + // Case 2: redundant language tags. + "sgn-BR": "bzs", + "sgn-CO": "csn", + "sgn-DE": "gsg", + "sgn-DK": "dsl", + "sgn-ES": "ssp", + "sgn-FR": "fsl", + "sgn-GB": "bfi", + "sgn-GR": "gss", + "sgn-IE": "isg", + "sgn-IT": "ise", + "sgn-JP": "jsl", + "sgn-MX": "mfs", + "sgn-NI": "ncs", + "sgn-NL": "dse", + "sgn-NO": "nsi", + "sgn-PT": "psr", + "sgn-SE": "swl", + "sgn-US": "ase", + "sgn-ZA": "sfs", + + // Case 3: the special case. + "ja-Latn-hepburn-heploc": "ja-Latn-alalc97", +}; +const extensions = ["-u-attr", "-u-nu-latn"]; +const intlConstructors = [Intl.Collator, Intl.DateTimeFormat, Intl.NumberFormat]; +const options = [{localeMatcher: "best fit"}, {localeMatcher: "lookup"}]; + +for (let [tag, canonical] of Object.entries(languageTags)) { + // Ensure Intl.getCanonicalLocales canonicalizes the language tag correctly. + assertEq(Intl.getCanonicalLocales(tag)[0], canonical); + + // Unicode extensions don't change the canonicalization result. + for (let ext of extensions) { + assertEq(Intl.getCanonicalLocales(tag + ext)[0], canonical + ext); + assertEq(Intl.getCanonicalLocales(canonical + ext)[0], canonical + ext); + } + + for (let intlCtor of intlConstructors) { + for (let opt of options) { + // The non-canonical tag is supported iff the canonical tag is supported. + let supported = intlCtor.supportedLocalesOf(tag, opt); + let supportedCanonical = intlCtor.supportedLocalesOf(canonical, opt); + assertEq(supported.length, supportedCanonical.length); + + let isSupported = supported.length > 0; + if (isSupported) { + assertEq(supported[0], canonical); + assertEq(supportedCanonical[0], canonical); + } + + // Unicode extensions don't change the result of supportedLocalesOf(). + for (let ext of extensions) { + let supportedExt = intlCtor.supportedLocalesOf(tag + ext, opt); + let supportedCanonicalExt = intlCtor.supportedLocalesOf(canonical + ext, opt); + assertEq(supportedExt.length, supportedCanonical.length); + assertEq(supportedCanonicalExt.length, supportedCanonical.length); + + if (isSupported) { + assertEq(supportedExt[0], canonical + ext); + assertEq(supportedCanonicalExt[0], canonical + ext); + } + } + } + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/resolved-locale-sorted-unicode-extension-keys.js b/js/src/tests/non262/Intl/resolved-locale-sorted-unicode-extension-keys.js new file mode 100644 index 0000000000..400f7f0f63 --- /dev/null +++ b/js/src/tests/non262/Intl/resolved-locale-sorted-unicode-extension-keys.js @@ -0,0 +1,109 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +function IsIntlService(c) { + return typeof c === "function" && + c.hasOwnProperty("prototype") && + c.prototype.hasOwnProperty("resolvedOptions"); +} + +const IntlServices = Object.getOwnPropertyNames(Intl).map(name => Intl[name]).filter(IsIntlService); + +// Examples for all possible Unicode extension keys (with the exception of deprecated "vt"). +const unicodeExtensions = [ + // calendar + "ca-gregory", + "fw-mon", + "hc-h23", + + // collation + "co-phonebk", + "ka-noignore", + "kb-false", + "kc-false", + "kf-false", + "kh-false", + "kk-false", + "kn-false", + "kr-space", + "ks-level1", + "kv-space", + + // currency + "cf-standard", + "cu-eur", + + // measure + "ms-metric", + + // number + "nu-latn", + + // segmentation + "lb-strict", + "lw-normal", + "ss-none", + + // timezone + "tz-atvie", + + // variant + "em-default", + "rg-atzzzz", + "sd-atat1", + "va-posix", +]; + +function reverse(a, b) { + if (a < b) { + return 1; + } + if (a > b) { + return -1; + } + return 0; +} + +function findUnicodeExtensionKeys(locale) { + // Find the Unicode extension key subtag. + var extension = locale.match(/.*-u-(.*)/); + if (extension === null) { + return []; + } + + // Replace all types in the Unicode extension keywords. + return extension[1].replace(/-\w{3,}/g, "").split("-"); +} + +// Test all Intl service constructors and ensure the Unicode extension keys in +// the resolved locale are sorted alphabetically. + +for (let IntlService of IntlServices) { + let options = undefined; + if (IntlService === Intl.DisplayNames) { + // Intl.DisplayNames requires the "type" option to be set. + options = {type: "language"}; + } + + // sort() modifies the input array, so create a copy. + let ext = unicodeExtensions.slice(0); + + let locale, keys; + + // Input keys unsorted. + locale = new IntlService(`de-u-${ext.join("-")}`, options).resolvedOptions().locale; + keys = findUnicodeExtensionKeys(locale); + assertEqArray(keys, keys.slice(0).sort()); + + // Input keys sorted alphabetically. + locale = new IntlService(`de-u-${ext.sort().join("-")}`, options).resolvedOptions().locale; + keys = findUnicodeExtensionKeys(locale); + assertEqArray(keys, keys.slice(0).sort()); + + // Input keys sorted alphabetically in reverse order. + locale = new IntlService(`de-u-${ext.sort(reverse).join("-")}`, options).resolvedOptions().locale; + keys = findUnicodeExtensionKeys(locale); + assertEqArray(keys, keys.slice(0).sort()); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/shell.js b/js/src/tests/non262/Intl/shell.js new file mode 100644 index 0000000000..1659e39e12 --- /dev/null +++ b/js/src/tests/non262/Intl/shell.js @@ -0,0 +1,340 @@ +// Generated by make_intl_data.py. DO NOT EDIT. + +// source: CLDR file common/bcp47/number.xml; version CLDR 43. +// https://github.com/unicode-org/cldr/blob/master/common/bcp47/number.xml +// https://github.com/unicode-org/cldr/blob/master/common/supplemental/numberingSystems.xml +const numberingSystems = { + "adlm": { + "algorithmic": false, + "digits": "𞥐𞥑𞥒𞥓𞥔𞥕𞥖𞥗𞥘𞥙" + }, + "ahom": { + "algorithmic": false, + "digits": "𑜰𑜱𑜲𑜳𑜴𑜵𑜶𑜷𑜸𑜹" + }, + "arab": { + "algorithmic": false, + "digits": "٠١٢٣٤٥٦٧٨٩" + }, + "arabext": { + "algorithmic": false, + "digits": "۰۱۲۳۴۵۶۷۸۹" + }, + "armn": { + "algorithmic": true + }, + "armnlow": { + "algorithmic": true + }, + "bali": { + "algorithmic": false, + "digits": "᭐᭑᭒᭓᭔᭕᭖᭗᭘᭙" + }, + "beng": { + "algorithmic": false, + "digits": "০১২৩৪৫৬৭৮৯" + }, + "bhks": { + "algorithmic": false, + "digits": "𑱐𑱑𑱒𑱓𑱔𑱕𑱖𑱗𑱘𑱙" + }, + "brah": { + "algorithmic": false, + "digits": "𑁦𑁧𑁨𑁩𑁪𑁫𑁬𑁭𑁮𑁯" + }, + "cakm": { + "algorithmic": false, + "digits": "𑄶𑄷𑄸𑄹𑄺𑄻𑄼𑄽𑄾𑄿" + }, + "cham": { + "algorithmic": false, + "digits": "꩐꩑꩒꩓꩔꩕꩖꩗꩘꩙" + }, + "cyrl": { + "algorithmic": true + }, + "deva": { + "algorithmic": false, + "digits": "०१२३४५६७८९" + }, + "diak": { + "algorithmic": false, + "digits": "𑥐𑥑𑥒𑥓𑥔𑥕𑥖𑥗𑥘𑥙" + }, + "ethi": { + "algorithmic": true + }, + "fullwide": { + "algorithmic": false, + "digits": "0123456789" + }, + "geor": { + "algorithmic": true + }, + "gong": { + "algorithmic": false, + "digits": "𑶠𑶡𑶢𑶣𑶤𑶥𑶦𑶧𑶨𑶩" + }, + "gonm": { + "algorithmic": false, + "digits": "𑵐𑵑𑵒𑵓𑵔𑵕𑵖𑵗𑵘𑵙" + }, + "grek": { + "algorithmic": true + }, + "greklow": { + "algorithmic": true + }, + "gujr": { + "algorithmic": false, + "digits": "૦૧૨૩૪૫૬૭૮૯" + }, + "guru": { + "algorithmic": false, + "digits": "੦੧੨੩੪੫੬੭੮੯" + }, + "hanidays": { + "algorithmic": true + }, + "hanidec": { + "algorithmic": false, + "digits": "〇一二三四五六七八九" + }, + "hans": { + "algorithmic": true + }, + "hansfin": { + "algorithmic": true + }, + "hant": { + "algorithmic": true + }, + "hantfin": { + "algorithmic": true + }, + "hebr": { + "algorithmic": true + }, + "hmng": { + "algorithmic": false, + "digits": "𖭐𖭑𖭒𖭓𖭔𖭕𖭖𖭗𖭘𖭙" + }, + "hmnp": { + "algorithmic": false, + "digits": "𞅀𞅁𞅂𞅃𞅄𞅅𞅆𞅇𞅈𞅉" + }, + "java": { + "algorithmic": false, + "digits": "꧐꧑꧒꧓꧔꧕꧖꧗꧘꧙" + }, + "jpan": { + "algorithmic": true + }, + "jpanfin": { + "algorithmic": true + }, + "jpanyear": { + "algorithmic": true + }, + "kali": { + "algorithmic": false, + "digits": "꤀꤁꤂꤃꤄꤅꤆꤇꤈꤉" + }, + "kawi": { + "algorithmic": false, + "digits": "𑽐𑽑𑽒𑽓𑽔𑽕𑽖𑽗𑽘𑽙" + }, + "khmr": { + "algorithmic": false, + "digits": "០១២៣៤៥៦៧៨៩" + }, + "knda": { + "algorithmic": false, + "digits": "೦೧೨೩೪೫೬೭೮೯" + }, + "lana": { + "algorithmic": false, + "digits": "᪀᪁᪂᪃᪄᪅᪆᪇᪈᪉" + }, + "lanatham": { + "algorithmic": false, + "digits": "᪐᪑᪒᪓᪔᪕᪖᪗᪘᪙" + }, + "laoo": { + "algorithmic": false, + "digits": "໐໑໒໓໔໕໖໗໘໙" + }, + "latn": { + "algorithmic": false, + "digits": "0123456789" + }, + "lepc": { + "algorithmic": false, + "digits": "᱀᱁᱂᱃᱄᱅᱆᱇᱈᱉" + }, + "limb": { + "algorithmic": false, + "digits": "᥆᥇᥈᥉᥊᥋᥌᥍᥎᥏" + }, + "mathbold": { + "algorithmic": false, + "digits": "𝟎𝟏𝟐𝟑𝟒𝟓𝟔𝟕𝟖𝟗" + }, + "mathdbl": { + "algorithmic": false, + "digits": "𝟘𝟙𝟚𝟛𝟜𝟝𝟞𝟟𝟠𝟡" + }, + "mathmono": { + "algorithmic": false, + "digits": "𝟶𝟷𝟸𝟹𝟺𝟻𝟼𝟽𝟾𝟿" + }, + "mathsanb": { + "algorithmic": false, + "digits": "𝟬𝟭𝟮𝟯𝟰𝟱𝟲𝟳𝟴𝟵" + }, + "mathsans": { + "algorithmic": false, + "digits": "𝟢𝟣𝟤𝟥𝟦𝟧𝟨𝟩𝟪𝟫" + }, + "mlym": { + "algorithmic": false, + "digits": "൦൧൨൩൪൫൬൭൮൯" + }, + "modi": { + "algorithmic": false, + "digits": "𑙐𑙑𑙒𑙓𑙔𑙕𑙖𑙗𑙘𑙙" + }, + "mong": { + "algorithmic": false, + "digits": "᠐᠑᠒᠓᠔᠕᠖᠗᠘᠙" + }, + "mroo": { + "algorithmic": false, + "digits": "𖩠𖩡𖩢𖩣𖩤𖩥𖩦𖩧𖩨𖩩" + }, + "mtei": { + "algorithmic": false, + "digits": "꯰꯱꯲꯳꯴꯵꯶꯷꯸꯹" + }, + "mymr": { + "algorithmic": false, + "digits": "၀၁၂၃၄၅၆၇၈၉" + }, + "mymrshan": { + "algorithmic": false, + "digits": "႐႑႒႓႔႕႖႗႘႙" + }, + "mymrtlng": { + "algorithmic": false, + "digits": "꧰꧱꧲꧳꧴꧵꧶꧷꧸꧹" + }, + "nagm": { + "algorithmic": false, + "digits": "𞓰𞓱𞓲𞓳𞓴𞓵𞓶𞓷𞓸𞓹" + }, + "newa": { + "algorithmic": false, + "digits": "𑑐𑑑𑑒𑑓𑑔𑑕𑑖𑑗𑑘𑑙" + }, + "nkoo": { + "algorithmic": false, + "digits": "߀߁߂߃߄߅߆߇߈߉" + }, + "olck": { + "algorithmic": false, + "digits": "᱐᱑᱒᱓᱔᱕᱖᱗᱘᱙" + }, + "orya": { + "algorithmic": false, + "digits": "୦୧୨୩୪୫୬୭୮୯" + }, + "osma": { + "algorithmic": false, + "digits": "𐒠𐒡𐒢𐒣𐒤𐒥𐒦𐒧𐒨𐒩" + }, + "rohg": { + "algorithmic": false, + "digits": "𐴰𐴱𐴲𐴳𐴴𐴵𐴶𐴷𐴸𐴹" + }, + "roman": { + "algorithmic": true + }, + "romanlow": { + "algorithmic": true + }, + "saur": { + "algorithmic": false, + "digits": "꣐꣑꣒꣓꣔꣕꣖꣗꣘꣙" + }, + "segment": { + "algorithmic": false, + "digits": "🯰🯱🯲🯳🯴🯵🯶🯷🯸🯹" + }, + "shrd": { + "algorithmic": false, + "digits": "𑇐𑇑𑇒𑇓𑇔𑇕𑇖𑇗𑇘𑇙" + }, + "sind": { + "algorithmic": false, + "digits": "𑋰𑋱𑋲𑋳𑋴𑋵𑋶𑋷𑋸𑋹" + }, + "sinh": { + "algorithmic": false, + "digits": "෦෧෨෩෪෫෬෭෮෯" + }, + "sora": { + "algorithmic": false, + "digits": "𑃰𑃱𑃲𑃳𑃴𑃵𑃶𑃷𑃸𑃹" + }, + "sund": { + "algorithmic": false, + "digits": "᮰᮱᮲᮳᮴᮵᮶᮷᮸᮹" + }, + "takr": { + "algorithmic": false, + "digits": "𑛀𑛁𑛂𑛃𑛄𑛅𑛆𑛇𑛈𑛉" + }, + "talu": { + "algorithmic": false, + "digits": "᧐᧑᧒᧓᧔᧕᧖᧗᧘᧙" + }, + "taml": { + "algorithmic": true + }, + "tamldec": { + "algorithmic": false, + "digits": "௦௧௨௩௪௫௬௭௮௯" + }, + "telu": { + "algorithmic": false, + "digits": "౦౧౨౩౪౫౬౭౮౯" + }, + "thai": { + "algorithmic": false, + "digits": "๐๑๒๓๔๕๖๗๘๙" + }, + "tibt": { + "algorithmic": false, + "digits": "༠༡༢༣༤༥༦༧༨༩" + }, + "tirh": { + "algorithmic": false, + "digits": "𑓐𑓑𑓒𑓓𑓔𑓕𑓖𑓗𑓘𑓙" + }, + "tnsa": { + "algorithmic": false, + "digits": "𖫀𖫁𖫂𖫃𖫄𖫅𖫆𖫇𖫈𖫉" + }, + "vaii": { + "algorithmic": false, + "digits": "꘠꘡꘢꘣꘤꘥꘦꘧꘨꘩" + }, + "wara": { + "algorithmic": false, + "digits": "𑣠𑣡𑣢𑣣𑣤𑣥𑣦𑣧𑣨𑣩" + }, + "wcho": { + "algorithmic": false, + "digits": "𞋰𞋱𞋲𞋳𞋴𞋵𞋶𞋷𞋸𞋹" + } +}; diff --git a/js/src/tests/non262/Intl/supportedValuesOf-calendar.js b/js/src/tests/non262/Intl/supportedValuesOf-calendar.js new file mode 100644 index 0000000000..24a4ac3a57 --- /dev/null +++ b/js/src/tests/non262/Intl/supportedValuesOf-calendar.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const calendars = Intl.supportedValuesOf("calendar"); + +assertEq(new Set(calendars).size, calendars.length, "No duplicates are present"); +assertEqArray(calendars, [...calendars].sort(), "The list is sorted"); + +const typeRE = /^[a-z0-9]{3,8}(-[a-z0-9]{3,8})*$/; +for (let calendar of calendars) { + assertEq(typeRE.test(calendar), true, `${calendar} matches the 'type' production`); +} + +for (let calendar of calendars) { + assertEq(new Intl.Locale("und", {calendar}).calendar, calendar, `${calendar} is canonicalised`); +} + +for (let calendar of calendars) { + let obj = new Intl.DateTimeFormat("en", {calendar}); + assertEq(obj.resolvedOptions().calendar, calendar, `${calendar} is supported by DateTimeFormat`); +} + +assertEq(calendars.includes("gregory"), true, `Includes the Gregorian calendar`); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/supportedValuesOf-collation.js b/js/src/tests/non262/Intl/supportedValuesOf-collation.js new file mode 100644 index 0000000000..626bb28c20 --- /dev/null +++ b/js/src/tests/non262/Intl/supportedValuesOf-collation.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const collations = Intl.supportedValuesOf("collation"); + +assertEq(new Set(collations).size, collations.length, "No duplicates are present"); +assertEqArray(collations, [...collations].sort(), "The list is sorted"); + +const typeRE = /^[a-z0-9]{3,8}(-[a-z0-9]{3,8})*$/; +for (let collation of collations) { + assertEq(typeRE.test(collation), true, `${collation} matches the 'type' production`); +} + +for (let collation of collations) { + assertEq(new Intl.Locale("und", {collation}).collation, collation, `${collation} is canonicalised`); +} + +// Not all locales support all possible collations, so test the minimal set to +// cover all supported collations. +const locales = [ + "en", // "emoji", "eor" + "ar", // compat + "de", // phonebk + "es", // trad + "ko", // searchjl + "ln", // phonetic + "si", // dict + "sv", // reformed + "zh", // big5han, gb2312, pinyin, stroke, unihan, zhuyin +]; + +for (let collation of collations) { + let supported = false; + for (let locale of locales) { + let obj = new Intl.Collator(locale, {collation}); + if (obj.resolvedOptions().collation === collation) { + supported = true; + } + } + + assertEq(supported, true, `${collation} is supported by Collator`); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/supportedValuesOf-currency.js b/js/src/tests/non262/Intl/supportedValuesOf-currency.js new file mode 100644 index 0000000000..e2bf659e49 --- /dev/null +++ b/js/src/tests/non262/Intl/supportedValuesOf-currency.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const currencies = Intl.supportedValuesOf("currency"); + +assertEq(new Set(currencies).size, currencies.length, "No duplicates are present"); +assertEqArray(currencies, [...currencies].sort(), "The list is sorted"); + +const codeRE = /^[A-Z]{3}$/; +for (let currency of currencies) { + assertEq(codeRE.test(currency), true, `${currency} is a 3-letter ISO 4217 currency code`); +} + +for (let currency of currencies) { + let obj = new Intl.NumberFormat("en", {style: "currency", currency}); + assertEq(obj.resolvedOptions().currency, currency, `${currency} is supported by NumberFormat`); +} + +for (let currency of currencies) { + let obj = new Intl.DisplayNames("en", {type: "currency", fallback: "none"}); + assertEq(typeof obj.of(currency), "string", `${currency} is supported by DisplayNames`); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/supportedValuesOf-numberingSystem.js b/js/src/tests/non262/Intl/supportedValuesOf-numberingSystem.js new file mode 100644 index 0000000000..dd04094976 --- /dev/null +++ b/js/src/tests/non262/Intl/supportedValuesOf-numberingSystem.js @@ -0,0 +1,37 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const numSystems = Intl.supportedValuesOf("numberingSystem"); + +assertEq(new Set(numSystems).size, numSystems.length, "No duplicates are present"); +assertEqArray(numSystems, [...numSystems].sort(), "The list is sorted"); + +const typeRE = /^[a-z0-9]{3,8}(-[a-z0-9]{3,8})*$/; +for (let numberingSystem of numSystems) { + assertEq(typeRE.test(numberingSystem), true, `${numberingSystem} matches the 'type' production`); +} + +for (let numberingSystem of numSystems) { + assertEq(new Intl.Locale("und", {numberingSystem}).numberingSystem, numberingSystem, + `${numberingSystem} is canonicalised`); +} + +for (let numberingSystem of numSystems) { + let obj = new Intl.DateTimeFormat("en", {numberingSystem}); + assertEq(obj.resolvedOptions().numberingSystem, numberingSystem, + `${numberingSystem} is supported by DateTimeFormat`); +} + +for (let numberingSystem of numSystems) { + let obj = new Intl.NumberFormat("en", {numberingSystem}); + assertEq(obj.resolvedOptions().numberingSystem, numberingSystem, + `${numberingSystem} is supported by NumberFormat`); +} + +for (let numberingSystem of numSystems) { + let obj = new Intl.RelativeTimeFormat("en", {numberingSystem}); + assertEq(obj.resolvedOptions().numberingSystem, numberingSystem, + `${numberingSystem} is supported by RelativeTimeFormat`); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/supportedValuesOf-timeZones-canonical.js b/js/src/tests/non262/Intl/supportedValuesOf-timeZones-canonical.js new file mode 100644 index 0000000000..c134858f5c --- /dev/null +++ b/js/src/tests/non262/Intl/supportedValuesOf-timeZones-canonical.js @@ -0,0 +1,487 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Generated by make_intl_data.py. DO NOT EDIT. +// tzdata version = 2024a + +// This file was generated with historical, pre-1970 backzone information +// respected. + +const zones = [ + "Africa/Abidjan", + "Africa/Accra", + "Africa/Addis_Ababa", + "Africa/Algiers", + "Africa/Asmara", + "Africa/Bamako", + "Africa/Bangui", + "Africa/Banjul", + "Africa/Bissau", + "Africa/Blantyre", + "Africa/Brazzaville", + "Africa/Bujumbura", + "Africa/Cairo", + "Africa/Casablanca", + "Africa/Ceuta", + "Africa/Conakry", + "Africa/Dakar", + "Africa/Dar_es_Salaam", + "Africa/Djibouti", + "Africa/Douala", + "Africa/El_Aaiun", + "Africa/Freetown", + "Africa/Gaborone", + "Africa/Harare", + "Africa/Johannesburg", + "Africa/Juba", + "Africa/Kampala", + "Africa/Khartoum", + "Africa/Kigali", + "Africa/Kinshasa", + "Africa/Lagos", + "Africa/Libreville", + "Africa/Lome", + "Africa/Luanda", + "Africa/Lubumbashi", + "Africa/Lusaka", + "Africa/Malabo", + "Africa/Maputo", + "Africa/Maseru", + "Africa/Mbabane", + "Africa/Mogadishu", + "Africa/Monrovia", + "Africa/Nairobi", + "Africa/Ndjamena", + "Africa/Niamey", + "Africa/Nouakchott", + "Africa/Ouagadougou", + "Africa/Porto-Novo", + "Africa/Sao_Tome", + "Africa/Timbuktu", + "Africa/Tripoli", + "Africa/Tunis", + "Africa/Windhoek", + "America/Adak", + "America/Anchorage", + "America/Anguilla", + "America/Antigua", + "America/Araguaina", + "America/Argentina/Buenos_Aires", + "America/Argentina/Catamarca", + "America/Argentina/ComodRivadavia", + "America/Argentina/Cordoba", + "America/Argentina/Jujuy", + "America/Argentina/La_Rioja", + "America/Argentina/Mendoza", + "America/Argentina/Rio_Gallegos", + "America/Argentina/Salta", + "America/Argentina/San_Juan", + "America/Argentina/San_Luis", + "America/Argentina/Tucuman", + "America/Argentina/Ushuaia", + "America/Aruba", + "America/Asuncion", + "America/Atikokan", + "America/Bahia", + "America/Bahia_Banderas", + "America/Barbados", + "America/Belem", + "America/Belize", + "America/Blanc-Sablon", + "America/Boa_Vista", + "America/Bogota", + "America/Boise", + "America/Cambridge_Bay", + "America/Campo_Grande", + "America/Cancun", + "America/Caracas", + "America/Cayenne", + "America/Cayman", + "America/Chicago", + "America/Chihuahua", + "America/Ciudad_Juarez", + "America/Coral_Harbour", + "America/Costa_Rica", + "America/Creston", + "America/Cuiaba", + "America/Curacao", + "America/Danmarkshavn", + "America/Dawson", + "America/Dawson_Creek", + "America/Denver", + "America/Detroit", + "America/Dominica", + "America/Edmonton", + "America/Eirunepe", + "America/El_Salvador", + "America/Ensenada", + "America/Fort_Nelson", + "America/Fortaleza", + "America/Glace_Bay", + "America/Goose_Bay", + "America/Grand_Turk", + "America/Grenada", + "America/Guadeloupe", + "America/Guatemala", + "America/Guayaquil", + "America/Guyana", + "America/Halifax", + "America/Havana", + "America/Hermosillo", + "America/Indiana/Indianapolis", + "America/Indiana/Knox", + "America/Indiana/Marengo", + "America/Indiana/Petersburg", + "America/Indiana/Tell_City", + "America/Indiana/Vevay", + "America/Indiana/Vincennes", + "America/Indiana/Winamac", + "America/Inuvik", + "America/Iqaluit", + "America/Jamaica", + "America/Juneau", + "America/Kentucky/Louisville", + "America/Kentucky/Monticello", + "America/La_Paz", + "America/Lima", + "America/Los_Angeles", + "America/Maceio", + "America/Managua", + "America/Manaus", + "America/Martinique", + "America/Matamoros", + "America/Mazatlan", + "America/Menominee", + "America/Merida", + "America/Metlakatla", + "America/Mexico_City", + "America/Miquelon", + "America/Moncton", + "America/Monterrey", + "America/Montevideo", + "America/Montreal", + "America/Montserrat", + "America/Nassau", + "America/New_York", + "America/Nipigon", + "America/Nome", + "America/Noronha", + "America/North_Dakota/Beulah", + "America/North_Dakota/Center", + "America/North_Dakota/New_Salem", + "America/Nuuk", + "America/Ojinaga", + "America/Panama", + "America/Pangnirtung", + "America/Paramaribo", + "America/Phoenix", + "America/Port-au-Prince", + "America/Port_of_Spain", + "America/Porto_Velho", + "America/Puerto_Rico", + "America/Punta_Arenas", + "America/Rainy_River", + "America/Rankin_Inlet", + "America/Recife", + "America/Regina", + "America/Resolute", + "America/Rio_Branco", + "America/Rosario", + "America/Santarem", + "America/Santiago", + "America/Santo_Domingo", + "America/Sao_Paulo", + "America/Scoresbysund", + "America/Sitka", + "America/St_Johns", + "America/St_Kitts", + "America/St_Lucia", + "America/St_Thomas", + "America/St_Vincent", + "America/Swift_Current", + "America/Tegucigalpa", + "America/Thule", + "America/Thunder_Bay", + "America/Tijuana", + "America/Toronto", + "America/Tortola", + "America/Vancouver", + "America/Whitehorse", + "America/Winnipeg", + "America/Yakutat", + "America/Yellowknife", + "Antarctica/Casey", + "Antarctica/Davis", + "Antarctica/DumontDUrville", + "Antarctica/Macquarie", + "Antarctica/Mawson", + "Antarctica/McMurdo", + "Antarctica/Palmer", + "Antarctica/Rothera", + "Antarctica/Syowa", + "Antarctica/Troll", + "Antarctica/Vostok", + "Asia/Aden", + "Asia/Almaty", + "Asia/Amman", + "Asia/Anadyr", + "Asia/Aqtau", + "Asia/Aqtobe", + "Asia/Ashgabat", + "Asia/Atyrau", + "Asia/Baghdad", + "Asia/Bahrain", + "Asia/Baku", + "Asia/Bangkok", + "Asia/Barnaul", + "Asia/Beirut", + "Asia/Bishkek", + "Asia/Brunei", + "Asia/Chita", + "Asia/Choibalsan", + "Asia/Chongqing", + "Asia/Colombo", + "Asia/Damascus", + "Asia/Dhaka", + "Asia/Dili", + "Asia/Dubai", + "Asia/Dushanbe", + "Asia/Famagusta", + "Asia/Gaza", + "Asia/Harbin", + "Asia/Hebron", + "Asia/Ho_Chi_Minh", + "Asia/Hong_Kong", + "Asia/Hovd", + "Asia/Irkutsk", + "Asia/Jakarta", + "Asia/Jayapura", + "Asia/Jerusalem", + "Asia/Kabul", + "Asia/Kamchatka", + "Asia/Karachi", + "Asia/Kashgar", + "Asia/Kathmandu", + "Asia/Khandyga", + "Asia/Kolkata", + "Asia/Krasnoyarsk", + "Asia/Kuala_Lumpur", + "Asia/Kuching", + "Asia/Kuwait", + "Asia/Macau", + "Asia/Magadan", + "Asia/Makassar", + "Asia/Manila", + "Asia/Muscat", + "Asia/Nicosia", + "Asia/Novokuznetsk", + "Asia/Novosibirsk", + "Asia/Omsk", + "Asia/Oral", + "Asia/Phnom_Penh", + "Asia/Pontianak", + "Asia/Pyongyang", + "Asia/Qatar", + "Asia/Qostanay", + "Asia/Qyzylorda", + "Asia/Riyadh", + "Asia/Sakhalin", + "Asia/Samarkand", + "Asia/Seoul", + "Asia/Shanghai", + "Asia/Singapore", + "Asia/Srednekolymsk", + "Asia/Taipei", + "Asia/Tashkent", + "Asia/Tbilisi", + "Asia/Tehran", + "Asia/Tel_Aviv", + "Asia/Thimphu", + "Asia/Tokyo", + "Asia/Tomsk", + "Asia/Ulaanbaatar", + "Asia/Urumqi", + "Asia/Ust-Nera", + "Asia/Vientiane", + "Asia/Vladivostok", + "Asia/Yakutsk", + "Asia/Yangon", + "Asia/Yekaterinburg", + "Asia/Yerevan", + "Atlantic/Azores", + "Atlantic/Bermuda", + "Atlantic/Canary", + "Atlantic/Cape_Verde", + "Atlantic/Faroe", + "Atlantic/Jan_Mayen", + "Atlantic/Madeira", + "Atlantic/Reykjavik", + "Atlantic/South_Georgia", + "Atlantic/St_Helena", + "Atlantic/Stanley", + "Australia/Adelaide", + "Australia/Brisbane", + "Australia/Broken_Hill", + "Australia/Currie", + "Australia/Darwin", + "Australia/Eucla", + "Australia/Hobart", + "Australia/Lindeman", + "Australia/Lord_Howe", + "Australia/Melbourne", + "Australia/Perth", + "Australia/Sydney", + "CET", + "CST6CDT", + "EET", + "EST", + "EST5EDT", + "Etc/GMT+1", + "Etc/GMT+10", + "Etc/GMT+11", + "Etc/GMT+12", + "Etc/GMT+2", + "Etc/GMT+3", + "Etc/GMT+4", + "Etc/GMT+5", + "Etc/GMT+6", + "Etc/GMT+7", + "Etc/GMT+8", + "Etc/GMT+9", + "Etc/GMT-1", + "Etc/GMT-10", + "Etc/GMT-11", + "Etc/GMT-12", + "Etc/GMT-13", + "Etc/GMT-14", + "Etc/GMT-2", + "Etc/GMT-3", + "Etc/GMT-4", + "Etc/GMT-5", + "Etc/GMT-6", + "Etc/GMT-7", + "Etc/GMT-8", + "Etc/GMT-9", + "Europe/Amsterdam", + "Europe/Andorra", + "Europe/Astrakhan", + "Europe/Athens", + "Europe/Belfast", + "Europe/Belgrade", + "Europe/Berlin", + "Europe/Brussels", + "Europe/Bucharest", + "Europe/Budapest", + "Europe/Chisinau", + "Europe/Copenhagen", + "Europe/Dublin", + "Europe/Gibraltar", + "Europe/Guernsey", + "Europe/Helsinki", + "Europe/Isle_of_Man", + "Europe/Istanbul", + "Europe/Jersey", + "Europe/Kaliningrad", + "Europe/Kirov", + "Europe/Kyiv", + "Europe/Lisbon", + "Europe/Ljubljana", + "Europe/London", + "Europe/Luxembourg", + "Europe/Madrid", + "Europe/Malta", + "Europe/Minsk", + "Europe/Monaco", + "Europe/Moscow", + "Europe/Oslo", + "Europe/Paris", + "Europe/Prague", + "Europe/Riga", + "Europe/Rome", + "Europe/Samara", + "Europe/Sarajevo", + "Europe/Saratov", + "Europe/Simferopol", + "Europe/Skopje", + "Europe/Sofia", + "Europe/Stockholm", + "Europe/Tallinn", + "Europe/Tirane", + "Europe/Tiraspol", + "Europe/Ulyanovsk", + "Europe/Uzhgorod", + "Europe/Vaduz", + "Europe/Vienna", + "Europe/Vilnius", + "Europe/Volgograd", + "Europe/Warsaw", + "Europe/Zagreb", + "Europe/Zaporozhye", + "Europe/Zurich", + "Factory", + "HST", + "Indian/Antananarivo", + "Indian/Chagos", + "Indian/Christmas", + "Indian/Cocos", + "Indian/Comoro", + "Indian/Kerguelen", + "Indian/Mahe", + "Indian/Maldives", + "Indian/Mauritius", + "Indian/Mayotte", + "Indian/Reunion", + "MET", + "MST", + "MST7MDT", + "PST8PDT", + "Pacific/Apia", + "Pacific/Auckland", + "Pacific/Bougainville", + "Pacific/Chatham", + "Pacific/Chuuk", + "Pacific/Easter", + "Pacific/Efate", + "Pacific/Enderbury", + "Pacific/Fakaofo", + "Pacific/Fiji", + "Pacific/Funafuti", + "Pacific/Galapagos", + "Pacific/Gambier", + "Pacific/Guadalcanal", + "Pacific/Guam", + "Pacific/Honolulu", + "Pacific/Johnston", + "Pacific/Kanton", + "Pacific/Kiritimati", + "Pacific/Kosrae", + "Pacific/Kwajalein", + "Pacific/Majuro", + "Pacific/Marquesas", + "Pacific/Midway", + "Pacific/Nauru", + "Pacific/Niue", + "Pacific/Norfolk", + "Pacific/Noumea", + "Pacific/Pago_Pago", + "Pacific/Palau", + "Pacific/Pitcairn", + "Pacific/Pohnpei", + "Pacific/Port_Moresby", + "Pacific/Rarotonga", + "Pacific/Saipan", + "Pacific/Tahiti", + "Pacific/Tarawa", + "Pacific/Tongatapu", + "Pacific/Wake", + "Pacific/Wallis", + "UTC", + "WET", +]; + +let supported = Intl.supportedValuesOf("timeZone"); + +assertEqArray(supported, zones); + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); + diff --git a/js/src/tests/non262/Intl/supportedValuesOf-timeZones.js b/js/src/tests/non262/Intl/supportedValuesOf-timeZones.js new file mode 100644 index 0000000000..6a200cd199 --- /dev/null +++ b/js/src/tests/non262/Intl/supportedValuesOf-timeZones.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const timeZones = Intl.supportedValuesOf("timeZone"); + +assertEq(new Set(timeZones).size, timeZones.length, "No duplicates are present"); +assertEqArray(timeZones, [...timeZones].sort(), "The list is sorted"); + +// The pattern doesn't cover the complete time zone syntax, but gives a good first approximation. +const timeZoneRE = /^[a-z0-9_+-]+(\/[a-z0-9_+-]+)*$/i; +for (let timeZone of timeZones) { + assertEq(timeZoneRE.test(timeZone), true, `${timeZone} is ASCII`); +} + +for (let timeZone of timeZones) { + let obj = new Intl.DateTimeFormat("en", {timeZone}); + assertEq(obj.resolvedOptions().timeZone, timeZone, `${timeZone} is supported by DateTimeFormat`); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/supportedValuesOf-unit.js b/js/src/tests/non262/Intl/supportedValuesOf-unit.js new file mode 100644 index 0000000000..01dc5bb05c --- /dev/null +++ b/js/src/tests/non262/Intl/supportedValuesOf-unit.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const units = Intl.supportedValuesOf("unit"); + +assertEq(new Set(units).size, units.length, "No duplicates are present"); +assertEqArray(units, [...units].sort(), "The list is sorted"); + +const unitRE = /^[a-z]+(-[a-z]+)*$/; +for (let unit of units) { + assertEq(unitRE.test(unit), true, `${unit} is ASCII lower-case, separated by hyphens`); + assertEq(unit.includes("-per-"), false, `${unit} is a simple unit identifier`); +} + +for (let unit of units) { + let obj = new Intl.NumberFormat("en", {style: "unit", unit}); + assertEq(obj.resolvedOptions().unit, unit, `${unit} is supported by NumberFormat`); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/tolower-ascii-equivalent.js b/js/src/tests/non262/Intl/tolower-ascii-equivalent.js new file mode 100644 index 0000000000..ac3cbfb7d3 --- /dev/null +++ b/js/src/tests/non262/Intl/tolower-ascii-equivalent.js @@ -0,0 +1,47 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Language tags are processed case-insensitive, but unconditionally calling +// the built-in String.prototype.toLowerCase() or toUpperCase() function +// before parsing a language tag can map non-ASCII characters into the ASCII +// range. +// +// Validate the Unicode BCP 47 locale identifier parser handles this case +// (pun intended) correctly by passing language tags which contain +// U+212A (KELVIN SIGN) and U+0131 (LATIN SMALL LETTER DOTLESS I) to +// Intl.getCanonicalLocales(). + +// The lower-case form of "i-ha\u212A" is "i-hak". +assertEq("i-hak", "i-ha\u212A".toLowerCase()); + +// The upper-case form of "\u0131-hak" is "I-HAK". +assertEq("I-HAK", "\u0131-hak".toUpperCase()); + +// "i-hak" is not a valid Unicode BCP 47 locale identifier. +assertThrowsInstanceOf(() => Intl.getCanonicalLocales("i-hak"), RangeError); + +// And neither is "i-ha\u212A". +assertThrowsInstanceOf(() => Intl.getCanonicalLocales("i-ha\u212A"), RangeError); + +// And also "\u0131-hak" isn't valid. +assertThrowsInstanceOf(() => Intl.getCanonicalLocales("\u0131-hak"), RangeError); + +// The lower-case form of "zh-ha\u212A\u212Aa" is "zh-hakka". +assertEq("zh-hakka", "zh-ha\u212A\u212Aa".toLowerCase()); + +// "zh-hakka" is a valid Unicode BCP 47 locale identifier. +assertEqArray(Intl.getCanonicalLocales("zh-hakka"), ["hak"]); + +// But "zh-ha\u212A\u212Aa" is not a valid locale identifier. +assertThrowsInstanceOf(() => Intl.getCanonicalLocales("zh-ha\u212A\u212Aa"), RangeError); + +// The lower-case form of "zh-x\u0131ang" is "ZH-XIANG". +assertEq("ZH-XIANG", "zh-x\u0131ang".toUpperCase()); + +// "zh-xiang" is a valid Unicode BCP 47 locale identifier. +assertEqArray(Intl.getCanonicalLocales("zh-xiang"), ["hsn"]); + +// But "zh-x\u0131ang" is not a valid locale identifier. +assertThrowsInstanceOf(() => Intl.getCanonicalLocales("zh-x\u0131ang"), RangeError); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-extlangs.js b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-extlangs.js new file mode 100644 index 0000000000..7e9aae5519 --- /dev/null +++ b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-extlangs.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Unicode BCP 47 locale identifiers don't support extlang subtags. +const invalid = [ + // Two letter language code followed by extlang subtags. + "en-abc", + "en-abc-def", + "en-abc-def-ghi", + + // Three letter language code followed by extlang subtags. + "und-abc", + "und-abc-def", + "und-abc-def-ghi", +]; + +for (let locale of invalid) { + assertThrowsInstanceOf(() => Intl.getCanonicalLocales(locale), RangeError); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-language-mappings.js b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-language-mappings.js new file mode 100644 index 0000000000..4f0a01a9cb --- /dev/null +++ b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-language-mappings.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// For the most part the mappings from IANA are a subset of the CLDR mappings. +// So there are mappings which are consistent across both databases. +assertEq(Intl.getCanonicalLocales("iw")[0], "he"); + +// But some languages are mapped differently. +// +// From the IANA language data registry: +// Type: language +// Subtag: drh +// Description: Darkhat +// Added: 2009-07-29 +// Deprecated: 2010-03-11 +// Preferred-Value: khk +// +// From CLDR: +// +// +// because CLDR also maps macro-languages: +// +assertEq(Intl.getCanonicalLocales("drh")[0], "mn"); + +// CLDR maps macro-languages: +// +assertEq(Intl.getCanonicalLocales("cmn")[0], "zh"); + +// CLDR also contains mappings from ISO-639-2 (B/T) to 639-1 codes: +// +// +assertEq(Intl.getCanonicalLocales("dut")[0], "nl"); +assertEq(Intl.getCanonicalLocales("nld")[0], "nl"); + +// CLDR has additional mappings for legacy language codes. +// +assertEq(Intl.getCanonicalLocales("tl")[0], "fil"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-languages-mappings-complex.js b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-languages-mappings-complex.js new file mode 100644 index 0000000000..320e1b02c0 --- /dev/null +++ b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-languages-mappings-complex.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// CLDR contains language mappings where in addition to the language subtag also +// the script or region subtag is modified, unless they're already present. + +// +assertEq(Intl.getCanonicalLocales("sh")[0], "sr-Latn"); +assertEq(Intl.getCanonicalLocales("sh-RS")[0], "sr-Latn-RS"); +assertEq(Intl.getCanonicalLocales("sh-Cyrl")[0], "sr-Cyrl"); + +// +assertEq(Intl.getCanonicalLocales("cnr")[0], "sr-ME"); +assertEq(Intl.getCanonicalLocales("cnr-Latn")[0], "sr-Latn-ME"); +assertEq(Intl.getCanonicalLocales("cnr-RS")[0], "sr-RS"); + +// Aliases where more than just a language subtag are present are ignored. +// +assertEq(Intl.getCanonicalLocales("sr-RS")[0], "sr-RS"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-legacy.js b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-legacy.js new file mode 100644 index 0000000000..b7eefe2b75 --- /dev/null +++ b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-legacy.js @@ -0,0 +1,52 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Unicode BCP 47 locale identifiers don't support irregular legacy tags. +var irregularLegacy = [ + "en-gb-oed", + "i-ami", + "i-bnn", + "i-default", + "i-enochian", + "i-hak", + "i-klingon", + "i-lux", + "i-mingo", + "i-navajo", + "i-pwn", + "i-tao", + "i-tay", + "i-tsu", + "sgn-be-fr", + "sgn-be-nl", + "sgn-ch-de", +]; + +// Unicode BCP 47 locale identifiers don't support regular legacy tags +// which contain an extlang-like subtag. +var regularLegacyWithExtlangLike = [ + "no-bok", + "no-nyn", + "zh-min", + "zh-min-nan", +]; + +// Unicode BCP 47 locale identifiers do support regular legacy tags +// which contain a variant-like subtag. +var regularLegacyWithVariantLike = { + "art-lojban": "jbo", + "cel-gaulish": "xtg", + "zh-guoyu": "zh", + "zh-hakka": "hak", + "zh-xiang": "hsn", +}; + +for (let locale of [...irregularLegacy, ...regularLegacyWithExtlangLike]) { + assertThrowsInstanceOf(() => Intl.getCanonicalLocales(locale), RangeError); +} + +for (let [locale, canonical] of Object.entries(regularLegacyWithVariantLike)) { + assertEq(Intl.getCanonicalLocales(locale)[0], canonical); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-region-and-subdivision.js b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-region-and-subdivision.js new file mode 100644 index 0000000000..c9e1bd3951 --- /dev/null +++ b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-region-and-subdivision.js @@ -0,0 +1,12 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// +assertEq(Intl.getCanonicalLocales("fr-u-rg-frg")[0], "fr-u-rg-frges"); +assertEq(Intl.getCanonicalLocales("fr-u-sd-frg")[0], "fr-u-sd-frges"); + +// +assertEq(Intl.getCanonicalLocales("fr-u-rg-frgf")[0], "fr-u-rg-gfzzzz"); +assertEq(Intl.getCanonicalLocales("fr-u-sd-frgf")[0], "fr-u-sd-gfzzzz"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-region-mappings-complex.js b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-region-mappings-complex.js new file mode 100644 index 0000000000..22dbd17a1d --- /dev/null +++ b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-region-mappings-complex.js @@ -0,0 +1,57 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// CLDR contains region mappings where the replacement region depends on the +// likely subtags from the language and script subtags. +// +// For example, the breakup of the Soviet Union ("SU") means that the region of +// the Soviet Union ("SU") is replaced by Russia ("RU"), Armenia ("AM"), or +// many others -- depending on the specified (or merely likely) language and +// script subtags: +// +// +// +// Armenia can be the preferred region when the language is "hy" (Armenian) or +// the script is "Armn" (Armenian). +// +// +// +assertEq(Intl.getCanonicalLocales("ru-SU")[0], "ru-RU"); +assertEq(Intl.getCanonicalLocales("en-SU")[0], "en-RU"); +assertEq(Intl.getCanonicalLocales("und-SU")[0], "und-RU"); +assertEq(Intl.getCanonicalLocales("und-Latn-SU")[0], "und-Latn-RU"); +assertEq(Intl.getCanonicalLocales("hy-SU")[0], "hy-AM"); +assertEq(Intl.getCanonicalLocales("und-Armn-SU")[0], "und-Armn-AM"); + +// +// +// The following likely-subtags entries contain "RS" and "ME": +// +// +// +// +// +// +// In this case there is no language/script combination (without a region +// subtag) where "ME" is ever chosen, so the replacement is always "RS". +assertEq(Intl.getCanonicalLocales("sr-CS")[0], "sr-RS"); +assertEq(Intl.getCanonicalLocales("sr-Latn-CS")[0], "sr-Latn-RS"); +assertEq(Intl.getCanonicalLocales("sr-Cyrl-CS")[0], "sr-Cyrl-RS"); + +// The existing region in the source locale identifier is ignored when selecting +// the likely replacement region. For example take "az-NT", which is Azerbaijani +// spoken in the Neutral Zone. The replacement region for "NT" is either +// "SA" (Saudi-Arabia) or "IQ" (Iraq), and there is also a likely subtags entry +// for "az-IQ". But when only looking at the language subtag in "az-NT", "az" is +// always resolved to "az-Latn-AZ", and because "AZ" is not in the list ["SA", +// "IQ"], the final replacement region is the default for "NT", namely "SA". +// That means "az-NT" will be canonicalised to "az-SA" and not "az-IQ", even +// though the latter may be a more sensible candidate based on the actual usage +// of the target locales. +// +// +// +// +assertEq(Intl.getCanonicalLocales("az-NT")[0], "az-SA"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-region-mappings.js b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-region-mappings.js new file mode 100644 index 0000000000..affebb33b8 --- /dev/null +++ b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-region-mappings.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// For the most part the mappings from IANA are a subset of the CLDR mappings. +// So there are mappings which are consistent across both databases. +assertEq(Intl.getCanonicalLocales("de-DD")[0], "de-DE"); + +// CLDR contains additional mappings: +// +// +assertEq(Intl.getCanonicalLocales("und-QU")[0], "und-EU"); +assertEq(Intl.getCanonicalLocales("en-UK")[0], "en-GB"); + +// CLDR additional maps ISO 3166-1 numeric to ISO 3166-1 alpha-2 codes: +// +// +// +assertEq(Intl.getCanonicalLocales("de-280")[0], "de-DE"); +assertEq(Intl.getCanonicalLocales("de-278")[0], "de-DE"); +assertEq(Intl.getCanonicalLocales("de-276")[0], "de-DE"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-sign-languages.js b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-sign-languages.js new file mode 100644 index 0000000000..9f7b01c69e --- /dev/null +++ b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-sign-languages.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// The IANA language subtag registry contains replacements for sign language +// codes marked as redundant. For example: +// +// Type: redundant +// Tag: sgn-DE +// Description: German Sign Language +// Added: 2001-11-11 +// Deprecated: 2009-07-29 +// Preferred-Value: gsg +// +// CLDR 38 added these mappings to CLDR, too. + +assertEq(Intl.getCanonicalLocales("sgn-DE")[0], "gsg"); +assertEq(Intl.getCanonicalLocales("sgn-DD")[0], "gsg"); + +assertEq(Intl.getCanonicalLocales("sgn-276")[0], "gsg"); +assertEq(Intl.getCanonicalLocales("sgn-278")[0], "gsg"); +assertEq(Intl.getCanonicalLocales("sgn-280")[0], "gsg"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-transformed-ext.js b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-transformed-ext.js new file mode 100644 index 0000000000..50ac20e58b --- /dev/null +++ b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-transformed-ext.js @@ -0,0 +1,71 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +const invalid = [ + // empty + "en-t", + "en-t-a", + "en-t-x", + "en-t-0", + + // incomplete + "en-t-", + "en-t-en-", + "en-t-0x-", + + // tlang: unicode_language_subtag must be 2-3 or 5-8 characters and mustn't + // contain extlang subtags. + "en-t-root", + "en-t-abcdefghi", + "en-t-ar-aao", + + // tlang: unicode_script_subtag must be 4 alphabetical characters, can't + // be repeated. + "en-t-en-lat0", + "en-t-en-latn-latn", + + // tlang: unicode_region_subtag must either be 2 alpha characters or a three + // digit code. + "en-t-en-0", + "en-t-en-00", + "en-t-en-0x", + "en-t-en-x0", + "en-t-en-latn-0", + "en-t-en-latn-00", + "en-t-en-latn-xyz", + + // tlang: unicode_variant_subtag is either 5-8 alphanum characters or 4 + // characters starting with a digit. + "en-t-en-abcdefghi", + "en-t-en-latn-gb-ab", + "en-t-en-latn-gb-abc", + "en-t-en-latn-gb-abcd", + "en-t-en-latn-gb-abcdefghi", +]; + +// Canonicalisation also applies for the transformation extension. But also +// see . +const valid = [ + {locale: "en-t-en", canonical: "en-t-en"}, + {locale: "en-t-en-latn", canonical: "en-t-en-latn"}, + {locale: "en-t-en-ca", canonical: "en-t-en-ca"}, + {locale: "en-t-en-latn-ca", canonical: "en-t-en-latn-ca"}, + {locale: "en-t-en-emodeng", canonical: "en-t-en-emodeng"}, + {locale: "en-t-en-latn-emodeng", canonical: "en-t-en-latn-emodeng"}, + {locale: "en-t-en-latn-ca-emodeng", canonical: "en-t-en-latn-ca-emodeng"}, + {locale: "sl-t-sl-rozaj-biske-1994", canonical: "sl-t-sl-1994-biske-rozaj"}, + {locale: "DE-T-M0-DIN-K0-QWERTZ", canonical: "de-t-k0-qwertz-m0-din"}, + {locale: "en-t-m0-true", canonical: "en-t-m0-true"}, + {locale: "en-t-iw", canonical: "en-t-he"}, + {locale: "und-Latn-t-und-hani-m0-names", canonical: "und-Latn-t-und-hani-m0-prprname"}, +]; + +for (let locale of invalid) { + assertThrowsInstanceOf(() => Intl.getCanonicalLocales(locale), RangeError); +} + +for (let {locale, canonical} of valid) { + assertEq(Intl.getCanonicalLocales(locale)[0], canonical); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-unicode-ext.js b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-unicode-ext.js new file mode 100644 index 0000000000..a46eba475e --- /dev/null +++ b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-unicode-ext.js @@ -0,0 +1,12 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Unicode locale extension sequences don't allow keys with a digit as their +// second character. +assertThrowsInstanceOf(() => Intl.getCanonicalLocales("en-u-c0"), RangeError); +assertThrowsInstanceOf(() => Intl.getCanonicalLocales("en-u-00"), RangeError); + +// The first character is allowed to be a digit. +assertEq(Intl.getCanonicalLocales("en-u-0c")[0], "en-u-0c"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-variants-legacy-mappings.js b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-variants-legacy-mappings.js new file mode 100644 index 0000000000..41b2a9a5cb --- /dev/null +++ b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-variants-legacy-mappings.js @@ -0,0 +1,47 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// ECMA-402 includes mapping of legacy variants, as long as they're also present +// in in CLDR's supplementalMetadata.xml +// + +assertEq(Intl.getCanonicalLocales("sv-AALAND")[0], "sv-AX"); +assertEq(Intl.getCanonicalLocales("no-BOKMAL")[0], "nb"); +assertEq(Intl.getCanonicalLocales("no-NYNORSK")[0], "nn"); +assertEq(Intl.getCanonicalLocales("en-POSIX")[0], "en-posix"); +assertEq(Intl.getCanonicalLocales("el-POLYTONI")[0], "el-polyton"); +assertEq(Intl.getCanonicalLocales("aa-SAAHO")[0], "ssy"); + +// Additional cases from CLDR, version 38. + +assertEq(Intl.getCanonicalLocales("aar-saaho")[0], "ssy"); +assertEq(Intl.getCanonicalLocales("arm-arevmda")[0], "hyw"); +assertEq(Intl.getCanonicalLocales("hy-arevmda")[0], "hyw"); +assertEq(Intl.getCanonicalLocales("hye-arevmda")[0], "hyw"); + +for (let language of ["chi", "cmn", "zh", "zho"]) { + assertEq(Intl.getCanonicalLocales(language)[0], "zh"); + + let mapping = { + "guoyu-hakka": "hak", + "guoyu-xiang": "hsn", + "guoyu": "zh", + "hakka": "hak", + "xiang": "hsn", + }; + for (let [variant, canonical] of Object.entries(mapping)) { + assertEq(Intl.getCanonicalLocales(`${language}-${variant}`)[0], canonical); + } +} + +// Most legacy variant subtags are simply removed in contexts they don't apply. +for (let variant of ["arevela", "arevmda", "bokmal", "hakka", "lojban", "nynorsk", "saaho", "xiang"]) { + assertEq(Intl.getCanonicalLocales(`en-${variant}`)[0], "en"); +} + +// Except these three, whose replacement is always applied. +assertEq(Intl.getCanonicalLocales("en-aaland")[0], "en-AX"); +assertEq(Intl.getCanonicalLocales("en-heploc")[0], "en-alalc97"); +assertEq(Intl.getCanonicalLocales("en-polytoni")[0], "en-polyton"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-variants-sorted.js b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-variants-sorted.js new file mode 100644 index 0000000000..e50436a83c --- /dev/null +++ b/js/src/tests/non262/Intl/unicode-bcp47-locale-ids-variants-sorted.js @@ -0,0 +1,31 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// UTS 35, 3.2.1 Canonical Unicode Locale Identifiers: +// - Any variants are in alphabetical order. + +assertEq(Intl.getCanonicalLocales("en-scouse-fonipa")[0], "en-fonipa-scouse"); + +// Sorting in alphabetical order may turn a valid BCP 47 language tag into a +// BCP 47 language tag which is only well-formed, but no longer valid. This +// means there are potential compatibility issues when converting between +// Unicode BCP 47 locale identifiers and BCP 47 language tags. +// +// Spec: https://tools.ietf.org/html/rfc5646#section-2.2.9 + +// +// +// Type: variant +// Subtag: 1994 +// Description: Standardized Resian orthography +// Added: 2007-07-28 +// Prefix: sl-rozaj +// Prefix: sl-rozaj-biske +// Prefix: sl-rozaj-njiva +// Prefix: sl-rozaj-osojs +// Prefix: sl-rozaj-solba +// Comments: For standardized Resian an orthography was published in 1994. + +assertEq(Intl.getCanonicalLocales("sl-rozaj-biske-1994")[0], "sl-1994-biske-rozaj"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Intl/variant-with-preferred-value.js b/js/src/tests/non262/Intl/variant-with-preferred-value.js new file mode 100644 index 0000000000..751649a750 --- /dev/null +++ b/js/src/tests/non262/Intl/variant-with-preferred-value.js @@ -0,0 +1,58 @@ +// |reftest| skip-if(!this.hasOwnProperty("Intl")) + +// Per UTS 35, computing the canonical form for Unicode BCP 47 locale identifiers +// includes replacing deprecated variant mappings. The other UTS 35 canonicalisation +// algorithm ("BCP 47 Language Tag to Unicode BCP 47 Locale Identifier") doesn't +// support deprecated variant mappings. +// https://github.com/tc39/ecma402/issues/330 + +const languageTags = { + // The preferred value of "hy-arevela" is "hy" per CLDR. + "hy-arevela": "hy", + "hy-Armn-arevela": "hy-Armn", + "hy-AM-arevela": "hy-AM", + "hy-arevela-fonipa": "hy-fonipa", + "hy-fonipa-arevela": "hy-fonipa", + + // The preferred value of "hy-arevmda" is "hyw" per CLDR. + "hy-arevmda": "hyw", + "hy-Armn-arevmda": "hyw-Armn", + "hy-AM-arevmda": "hyw-AM", + "hy-arevmda-fonipa": "hyw-fonipa", + "hy-fonipa-arevmda": "hyw-fonipa", + + // The preferred value of "ja-Latn-hepburn-heploc" is "ja-Latn-alalc97" per CLDR and + // IANA. + "ja-Latn-hepburn-heploc": "ja-Latn-alalc97", + "ja-Latn-JP-hepburn-heploc": "ja-Latn-JP-alalc97", + + // Variant subtag replacements not present in IANA. + "sv-aaland": "sv-AX", + "el-polytoni": "el-polyton", + + // Additional cases when more variant subtags are present. + + // 1. The preferred variant is already present. + "ja-Latn-alalc97-hepburn-heploc": "ja-Latn-alalc97", + "ja-Latn-hepburn-alalc97-heploc": "ja-Latn-alalc97", + "ja-Latn-hepburn-heploc-alalc97": "ja-Latn-alalc97", + + // 2. The variant subtags aren't in the expected order per IANA. (CLDR doesn't care + // about the order of variant subtags.) + "ja-Latn-heploc-hepburn": "ja-Latn-alalc97", + + // 3. IANA expects both variant subtags to be present, CLDR also accepts single "heploc". + "ja-Latn-heploc": "ja-Latn-alalc97", + + // 4. Test for cases when the same variant subtag position needs to be checked more + // than once when replacing deprecated variant subtags. + "ja-Latn-aaland-heploc": "ja-Latn-AX-alalc97", + "ja-Latn-heploc-polytoni": "ja-Latn-alalc97-polyton", +}; + +for (let [tag, canonical] of Object.entries(languageTags)) { + assertEq(Intl.getCanonicalLocales(tag)[0], canonical); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/constructor-subclassable.js b/js/src/tests/non262/Iterator/constructor-subclassable.js new file mode 100644 index 0000000000..9f65c65ad0 --- /dev/null +++ b/js/src/tests/non262/Iterator/constructor-subclassable.js @@ -0,0 +1,12 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + Iterator constructor can be subclassed. +---*/ + +class TestIterator extends Iterator { +} + +assertEq(new TestIterator() instanceof Iterator, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/constructor-throw-when-called-directly.js b/js/src/tests/non262/Iterator/constructor-throw-when-called-directly.js new file mode 100644 index 0000000000..2b49b2d4ba --- /dev/null +++ b/js/src/tests/non262/Iterator/constructor-throw-when-called-directly.js @@ -0,0 +1,9 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + Iterator constructor throws when called directly. +---*/ + +assertThrowsInstanceOf(() => new Iterator(), TypeError); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/constructor-throw-without-new.js b/js/src/tests/non262/Iterator/constructor-throw-without-new.js new file mode 100644 index 0000000000..85497fcd63 --- /dev/null +++ b/js/src/tests/non262/Iterator/constructor-throw-without-new.js @@ -0,0 +1,9 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + Iterator constructor throws when called without new. +---*/ + +assertThrowsInstanceOf(() => Iterator(), TypeError); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/constructor.js b/js/src/tests/non262/Iterator/constructor.js new file mode 100644 index 0000000000..56d8271e82 --- /dev/null +++ b/js/src/tests/non262/Iterator/constructor.js @@ -0,0 +1,9 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + The Iterator constructor is a built-in function. +---*/ + +assertEq(typeof Iterator, 'function'); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/from/Iterator.from-descriptor.js b/js/src/tests/non262/Iterator/from/Iterator.from-descriptor.js new file mode 100644 index 0000000000..19bdde852b --- /dev/null +++ b/js/src/tests/non262/Iterator/from/Iterator.from-descriptor.js @@ -0,0 +1,12 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + Descriptor property of Iterator.from +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(Iterator, 'from'); +assertEq(propDesc.writable, true); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/from/Iterator.from-length.js b/js/src/tests/non262/Iterator/from/Iterator.from-length.js new file mode 100644 index 0000000000..0833538da1 --- /dev/null +++ b/js/src/tests/non262/Iterator/from/Iterator.from-length.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + The `length` property of Iterator.from. +info: | + ES7 section 17: Unless otherwise specified, the length property of a built-in + Function object has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(Iterator.from, 'length'); +assertEq(propDesc.value, 1); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/from/Iterator.from-name.js b/js/src/tests/non262/Iterator/from/Iterator.from-name.js new file mode 100644 index 0000000000..6f48d3e891 --- /dev/null +++ b/js/src/tests/non262/Iterator/from/Iterator.from-name.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + `name` property of Iterator.from. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(Iterator.from, 'name'); +assertEq(propDesc.value, 'from'); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/from/call-from-with-different-this.js b/js/src/tests/non262/Iterator/from/call-from-with-different-this.js new file mode 100644 index 0000000000..7016f7759b --- /dev/null +++ b/js/src/tests/non262/Iterator/from/call-from-with-different-this.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +const iter = { + next() { + assertEq(arguments.length, 0); + return {done: false, value: 0}; + }, +}; +const wrap = Iterator.from.call(undefined, iter); + +const result = wrap.next("next argument is ignored"); +assertEq(result.done, false); +assertEq(result.value, 0); + +const returnResult = wrap.return("return argument is ignored"); +assertEq(returnResult.done, true); +assertEq(returnResult.value, undefined); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/from/iterator-not-callable-throws.js b/js/src/tests/non262/Iterator/from/iterator-not-callable-throws.js new file mode 100644 index 0000000000..a7c98f9e2a --- /dev/null +++ b/js/src/tests/non262/Iterator/from/iterator-not-callable-throws.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + Iterator.from throws when called with an object with a non-callable @@iterator property. +---*/ + +assertThrowsInstanceOf(() => Iterator.from({ [Symbol.iterator]: 0 }), TypeError); +assertThrowsInstanceOf(() => Iterator.from({ [Symbol.iterator]: false }), TypeError); +assertThrowsInstanceOf(() => Iterator.from({ [Symbol.iterator]: "" }), TypeError); +assertThrowsInstanceOf(() => Iterator.from({ [Symbol.iterator]: {} }), TypeError); +assertThrowsInstanceOf(() => Iterator.from({ [Symbol.iterator]: Symbol('') }), TypeError); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/from/modify-next.js b/js/src/tests/non262/Iterator/from/modify-next.js new file mode 100644 index 0000000000..d347abd2cd --- /dev/null +++ b/js/src/tests/non262/Iterator/from/modify-next.js @@ -0,0 +1,15 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +const iter = { + next: () => ({ done: false, value: 0 }), +}; + +const wrap = Iterator.from(iter); + +iter.next = () => ({ done: true, value: undefined }); + +let {done, value} = wrap.next(); +assertEq(done, false); +assertEq(value, 0); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/from/modify-return.js b/js/src/tests/non262/Iterator/from/modify-return.js new file mode 100644 index 0000000000..dfda4dbe89 --- /dev/null +++ b/js/src/tests/non262/Iterator/from/modify-return.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +const iter = { + next: () => ({ done: false, value: 0 }), + return: (value = "old return") => ({ done: true, value }), +}; + +const wrap = Iterator.from(iter); + +let {done, value} = wrap.return("return argument ignored"); +assertEq(done, true); +assertEq(value, "old return"); + +iter.return = () => { throw new Error(); }; +assertThrowsInstanceOf(wrap.return, Error); + +iter.return = null; +let nullResult = wrap.return("return argument ignored"); +assertEq(nullResult.done, true); +assertEq(nullResult.value, undefined); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/from/o-not-object-throws.js b/js/src/tests/non262/Iterator/from/o-not-object-throws.js new file mode 100644 index 0000000000..3e6c00e59a --- /dev/null +++ b/js/src/tests/non262/Iterator/from/o-not-object-throws.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + Iterator.from throws when called with a non-object. +---*/ + +assertThrowsInstanceOf(() => Iterator.from(undefined), TypeError); +assertThrowsInstanceOf(() => Iterator.from(null), TypeError); +assertThrowsInstanceOf(() => Iterator.from(0), TypeError); +assertThrowsInstanceOf(() => Iterator.from(false), TypeError); +assertThrowsInstanceOf(() => Iterator.from(Symbol('')), TypeError); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/from/proxy-not-wrapped.js b/js/src/tests/non262/Iterator/from/proxy-not-wrapped.js new file mode 100644 index 0000000000..df38e0fc86 --- /dev/null +++ b/js/src/tests/non262/Iterator/from/proxy-not-wrapped.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +const log = []; +const handlerProxy = new Proxy({}, { + get: (target, key, receiver) => (...args) => { + log.push(`${key}: ${args[1]?.toString()}`); + + const item = Reflect[key](...args); + if (typeof item === 'function') + return (...args) => new Proxy(item.apply(receiver, args), handlerProxy); + return item; + }, +}); + +class Iter extends Iterator { + [Symbol.iterator]() { + return this; + } + next() { + return { done: false, value: 0 }; + } +} +const iter = new Iter(); +const proxy = new Proxy(iter, handlerProxy); +const wrap = Iterator.from(proxy); + +assertEq( + log.join('\n'), + `get: Symbol(Symbol.iterator) +get: next +getPrototypeOf: undefined` +); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/from/proxy-wrap-next.js b/js/src/tests/non262/Iterator/from/proxy-wrap-next.js new file mode 100644 index 0000000000..6be4e4b27b --- /dev/null +++ b/js/src/tests/non262/Iterator/from/proxy-wrap-next.js @@ -0,0 +1,30 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +const log = []; +const handlerProxy = new Proxy({}, { + get: (target, key, receiver) => (...args) => { + log.push(`${key}: ${args[1]?.toString()}`); + + const item = Reflect[key](...args); + if (typeof item === 'function') + return item.bind(receiver); + return item; + }, +}); +const iter = new Proxy({ + next: () => ({ done: false, value: 0 }), +}, handlerProxy); + +const wrap = Iterator.from(iter); +// Call next multiple times. Should not call `get` on proxy. +wrap.next(); +wrap.next(); +wrap.next(); + +assertEqArray(log, [ + "get: Symbol(Symbol.iterator)", + "get: next", + "getPrototypeOf: undefined", +]); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/from/proxy-wrap-return.js b/js/src/tests/non262/Iterator/from/proxy-wrap-return.js new file mode 100644 index 0000000000..ff72cbc231 --- /dev/null +++ b/js/src/tests/non262/Iterator/from/proxy-wrap-return.js @@ -0,0 +1,31 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +const log = []; +const handlerProxy = new Proxy({}, { + get: (target, key, receiver) => (...args) => { + log.push(`${key}: ${args[1]?.toString()}`); + + const item = Reflect[key](...args); + if (typeof item === 'function') + return item.bind(receiver); + return item; + }, +}); +const iter = new Proxy({ + next: () => ({ done: false, value: 0 }), + return: (value) => ({ done: true, value }), +}, handlerProxy); + +const wrap = Iterator.from(iter); +wrap.return(); +wrap.return(); + +assertEqArray(log, [ + "get: Symbol(Symbol.iterator)", + "get: next", + "getPrototypeOf: undefined", + "get: return", + "get: return", +]); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/from/return-iterator-if-iterable.js b/js/src/tests/non262/Iterator/from/return-iterator-if-iterable.js new file mode 100644 index 0000000000..e83e25185d --- /dev/null +++ b/js/src/tests/non262/Iterator/from/return-iterator-if-iterable.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + Iterator.from returns O if it is iterable, an iterator, and an instance of Iterator. +---*/ + +class TestIterator extends Iterator { + [Symbol.iterator]() { + return this; + } + + next() { + return { done: false, value: this.value++ }; + } + + value = 0; +} + +const iter = new TestIterator(); +assertEq(iter, Iterator.from(iter)); + +const arrayIter = [1, 2, 3][Symbol.iterator](); +assertEq(arrayIter, Iterator.from(arrayIter)); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/from/return-wrapper-if-not-iterable.js b/js/src/tests/non262/Iterator/from/return-wrapper-if-not-iterable.js new file mode 100644 index 0000000000..09b974f327 --- /dev/null +++ b/js/src/tests/non262/Iterator/from/return-wrapper-if-not-iterable.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + Iterator.from returns an iterator wrapper if O is not an iterable. +---*/ + +class TestIterator { + next() { + return { done: false, value: 0 }; + } +} + +const iter = new TestIterator(); +assertEq( + Symbol.iterator in iter, + false, + 'iter is not an iterable.' +); + +const wrapper = Iterator.from(iter); +assertEq(iter !== wrapper, true); +assertEq( + Symbol.iterator in wrapper, + true, + 'wrapper is an iterable.' +); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/from/return-wrapper-if-not-iterator-instance.js b/js/src/tests/non262/Iterator/from/return-wrapper-if-not-iterator-instance.js new file mode 100644 index 0000000000..4045801277 --- /dev/null +++ b/js/src/tests/non262/Iterator/from/return-wrapper-if-not-iterator-instance.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + Iterator.from returns an iterator wrapper if O is not an instance of Iterator. +---*/ + +class TestIterator { + [Symbol.iterator]() { + return this; + } + + next() { + return { done: false, value: 0 }; + } +} + +const iter = new TestIterator(); +assertEq(iter instanceof Iterator, false); + +const wrapper = Iterator.from(iter); +assertEq(iter !== wrapper, true); +assertEq(wrapper instanceof Iterator, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/from/wrap-functions-on-other-global.js b/js/src/tests/non262/Iterator/from/wrap-functions-on-other-global.js new file mode 100644 index 0000000000..a3d60d4b48 --- /dev/null +++ b/js/src/tests/non262/Iterator/from/wrap-functions-on-other-global.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +class TestError extends Error {} + +function checkIterResult({done, value}, expectedDone, expectedValue) { + assertEq(done, expectedDone); + assertEq(value, expectedValue); +} + +const iter = { + next(value) { + return {done: false, value: arguments.length}; + }, + return() { + throw new TestError(); + }, + throw: (value) => ({done: true, value}), +}; +const thisWrap = Iterator.from(iter); +const otherGlobal = newGlobal({newCompartment: true}); +const otherWrap = otherGlobal.Iterator.from(iter); + +checkIterResult(thisWrap.next.call(otherWrap), false, 0); +checkIterResult(thisWrap.next.call(otherWrap, 'value'), false, 0); + +assertThrowsInstanceOf(thisWrap.return.bind(otherWrap), TestError); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/from/wrap-method-with-non-wrap-this-throws.js b/js/src/tests/non262/Iterator/from/wrap-method-with-non-wrap-this-throws.js new file mode 100644 index 0000000000..7ff8539923 --- /dev/null +++ b/js/src/tests/non262/Iterator/from/wrap-method-with-non-wrap-this-throws.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +// All methods on %WrapForValidIteratorPrototype% require an [[Iterated]] +// internal slot on the `this` object. + +class TestIterator { + next() { + return { + done: false, + value: 0, + }; + } +} + +const nextMethod = Iterator.from(new TestIterator()).next; +assertThrowsInstanceOf(() => nextMethod.call(undefined), TypeError); +assertThrowsInstanceOf(() => nextMethod.call(null), TypeError); +assertThrowsInstanceOf(() => nextMethod.call(0), TypeError); +assertThrowsInstanceOf(() => nextMethod.call(false), TypeError); +assertThrowsInstanceOf(() => nextMethod.call('test'), TypeError); +assertThrowsInstanceOf(() => nextMethod.call(Object(1)), TypeError); +assertThrowsInstanceOf(() => nextMethod.call({}), TypeError); + +const returnMethod = Iterator.from(new TestIterator()).next; +assertThrowsInstanceOf(() => returnMethod.call(undefined), TypeError); +assertThrowsInstanceOf(() => returnMethod.call(null), TypeError); +assertThrowsInstanceOf(() => returnMethod.call(0), TypeError); +assertThrowsInstanceOf(() => returnMethod.call(false), TypeError); +assertThrowsInstanceOf(() => returnMethod.call('test'), TypeError); +assertThrowsInstanceOf(() => returnMethod.call(Object(1)), TypeError); +assertThrowsInstanceOf(() => returnMethod.call({}), TypeError); + +const throwMethod = Iterator.from(new TestIterator()).next; +assertThrowsInstanceOf(() => throwMethod.call(undefined), TypeError); +assertThrowsInstanceOf(() => throwMethod.call(null), TypeError); +assertThrowsInstanceOf(() => throwMethod.call(0), TypeError); +assertThrowsInstanceOf(() => throwMethod.call(false), TypeError); +assertThrowsInstanceOf(() => throwMethod.call('test'), TypeError); +assertThrowsInstanceOf(() => throwMethod.call(Object(1)), TypeError); +assertThrowsInstanceOf(() => throwMethod.call({}), TypeError); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/from/wrap-new-global.js b/js/src/tests/non262/Iterator/from/wrap-new-global.js new file mode 100644 index 0000000000..a9a26b41b0 --- /dev/null +++ b/js/src/tests/non262/Iterator/from/wrap-new-global.js @@ -0,0 +1,9 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +const otherGlobal = newGlobal({newCompartment: true}); + +const iter = [1, 2, 3].values(); +assertEq(iter, Iterator.from(iter)); +assertEq(iter !== otherGlobal.Iterator.from(iter), true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/from/wrap-next-forwards-value.js b/js/src/tests/non262/Iterator/from/wrap-next-forwards-value.js new file mode 100644 index 0000000000..bc7c1c4086 --- /dev/null +++ b/js/src/tests/non262/Iterator/from/wrap-next-forwards-value.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +class Iter { + next(value) { + assertEq(arguments.length, 0); + return { done: false, value }; + } +} + +const iter = new Iter(); +const wrap = Iterator.from(iter); +assertEq(iter !== wrap, true); + +assertEq(iter.v, undefined); +wrap.next(1); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/from/wrap-next-not-object-throws.js b/js/src/tests/non262/Iterator/from/wrap-next-not-object-throws.js new file mode 100644 index 0000000000..c2bc5442cf --- /dev/null +++ b/js/src/tests/non262/Iterator/from/wrap-next-not-object-throws.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +const iter = (value) => Iterator.from({ + next: () => value, +}); + +for (let value of [ + undefined, + null, + 0, + false, + "test", + Symbol(""), +]) { + assertEq(iter(value).next(), value); +} + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/from/wrap-return-closes-iterator.js b/js/src/tests/non262/Iterator/from/wrap-return-closes-iterator.js new file mode 100644 index 0000000000..c5d104db5c --- /dev/null +++ b/js/src/tests/non262/Iterator/from/wrap-return-closes-iterator.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +class Iter { + next() { + if (this.closed) + return { done: true, value: undefined }; + return { done: false, value: 0 }; + } + + return(value) { + assertEq(arguments.length, 0); + this.closed = true; + return { done: true, value: 42 }; + } +} + +const iter = new Iter(); +const wrap = Iterator.from(iter); +assertEq(iter.closed, undefined); + +let result = wrap.next(); +assertEq(result.done, false); +assertEq(result.value, 0); + +result = wrap.return(1); +assertEq(result.done, true); +assertEq(result.value, 42); + +assertEq(iter.closed, true); +result = wrap.next(); +assertEq(result.done, true); +assertEq(result.value, undefined); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/iterator.js b/js/src/tests/non262/Iterator/iterator.js new file mode 100644 index 0000000000..ad48fc2061 --- /dev/null +++ b/js/src/tests/non262/Iterator/iterator.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + Property descriptor of Iterator. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(this, 'Iterator'); +assertEq(propDesc.value, Iterator); +assertEq(propDesc.writable, true); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/length.js b/js/src/tests/non262/Iterator/length.js new file mode 100644 index 0000000000..07d1e4f804 --- /dev/null +++ b/js/src/tests/non262/Iterator/length.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + The "length" property of Iterator +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(Iterator, 'length'); +assertEq(propDesc.value, 0); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/name.js b/js/src/tests/non262/Iterator/name.js new file mode 100644 index 0000000000..c11e570228 --- /dev/null +++ b/js/src/tests/non262/Iterator/name.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + The "name" property of Iterator +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(Iterator, 'name'); +assertEq(propDesc.value, 'Iterator'); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/proto.js b/js/src/tests/non262/Iterator/proto.js new file mode 100644 index 0000000000..642e48d171 --- /dev/null +++ b/js/src/tests/non262/Iterator/proto.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + The prototype of the Iterator constructor is the intrinsic object %FunctionPrototype%. +---*/ + +assertEq(Object.getPrototypeOf(Iterator), Function.prototype); + +const propDesc = Reflect.getOwnPropertyDescriptor(Iterator, 'prototype'); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, false); + +// Make sure @@toStringTag has been set. +const toStringTagDesc = Reflect.getOwnPropertyDescriptor(Iterator.prototype, Symbol.toStringTag); +assertDeepEq(toStringTagDesc, { + value: "Iterator", + writable: true, + enumerable: false, + configurable: true, +}); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/drop/drop-more-than-available.js b/js/src/tests/non262/Iterator/prototype/drop/drop-more-than-available.js new file mode 100644 index 0000000000..230ebb8faf --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/drop/drop-more-than-available.js @@ -0,0 +1,37 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +// +// +/*--- +esid: pending +description: %Iterator.prototype%.drop returns if the iterator is done. +info: > + Iterator Helpers proposal 2.1.5.5 + 1. Repeat, while remaining > 0, + ... + b. Let next be ? IteratorStep(iterated). + c. If next is false, return undefined. +features: [iterator-helpers] +---*/ + +let iter = [1, 2].values().drop(3); +let result = iter.next(); +assertEq(result.value, undefined); +assertEq(result.done, true); + +class TestIterator extends Iterator { + counter = 0; + next() { + return {done: ++this.counter >= 2, value: undefined}; + } +} + +iter = new TestIterator(); +let dropped = iter.drop(10); +result = dropped.next(); +assertEq(result.value, undefined); +assertEq(result.done, true); +assertEq(iter.counter, 2); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/drop/drop.js b/js/src/tests/non262/Iterator/prototype/drop/drop.js new file mode 100644 index 0000000000..7ca1f34fbe --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/drop/drop.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +/*--- +esid: pending +description: Smoketest of %Iterator.prototype%.drop. +info: > + Iterator Helpers proposal 2.1.5.5 +features: [iterator-helpers] +---*/ + +let iter = [1, 2, 3].values().drop(1); + +for (const v of [2, 3]) { + let result = iter.next(); + assertEq(result.done, false); + assertEq(result.value, v); +} + +assertEq(iter.next().done, true); + +// `drop`, when called without arguments, throws a RangeError, +assertThrowsInstanceOf(() => ['test'].values().drop(), RangeError); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/drop/length.js b/js/src/tests/non262/Iterator/prototype/drop/length.js new file mode 100644 index 0000000000..d7dbcefcc5 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/drop/length.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) +// + +/*--- +esid: pending +description: %Iterator.prototype%.drop length value and descriptor. +info: > + 17 ECMAScript Standard Built-in Objects +includes: [propertyHelper.js] +features: [Symbol.iterator] +---*/ + +assertEq(Iterator.prototype.drop.length, 1); + +const propertyDescriptor = Reflect.getOwnPropertyDescriptor(Iterator.prototype.drop, 'length'); +assertEq(propertyDescriptor.value, 1); +assertEq(propertyDescriptor.enumerable, false); +assertEq(propertyDescriptor.writable, false); +assertEq(propertyDescriptor.configurable, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/drop/name.js b/js/src/tests/non262/Iterator/prototype/drop/name.js new file mode 100644 index 0000000000..06c904a21c --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/drop/name.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) +/*--- +esid: pending +description: %Iterator.prototype%.drop.name value and descriptor. +info: > + 17 ECMAScript Standard Built-in Objects +features: [iterator-helpers] +---*/ + +assertEq(Iterator.prototype.drop.name, 'drop'); + +const propertyDescriptor = Reflect.getOwnPropertyDescriptor(Iterator.prototype.drop, 'name'); +assertEq(propertyDescriptor.value, 'drop'); +assertEq(propertyDescriptor.enumerable, false); +assertEq(propertyDescriptor.writable, false); +assertEq(propertyDescriptor.configurable, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/every/check-fn-after-getting-iterator.js b/js/src/tests/non262/Iterator/prototype/every/check-fn-after-getting-iterator.js new file mode 100644 index 0000000000..7ebf33d3e0 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/every/check-fn-after-getting-iterator.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +const log = []; +const handlerProxy = new Proxy({}, { + get: (target, key, receiver) => (...args) => { + log.push(`${key}: ${args[1]?.toString()}`); + return Reflect[key](...args); + }, +}); + +class TestIterator extends Iterator { + next() { + return {done: true}; + } +} + +const iter = new Proxy(new TestIterator(), handlerProxy); +assertThrowsInstanceOf(() => iter.every(1), TypeError); + +assertEqArray( + log, + ["get: every"] +); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/every/coerce-result-to-boolean.js b/js/src/tests/non262/Iterator/prototype/every/coerce-result-to-boolean.js new file mode 100644 index 0000000000..4af9650ab8 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/every/coerce-result-to-boolean.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const fn = (value) => value; +assertEq([true].values().every(fn), true); +assertEq([1].values().every(fn), true); +assertEq([[]].values().every(fn), true); +assertEq([{}].values().every(fn), true); +assertEq(['test'].values().every(fn), true); + +assertEq([false].values().every(fn), false); +assertEq([0].values().every(fn), false); +assertEq([''].values().every(fn), false); +assertEq([null].values().every(fn), false); +assertEq([undefined].values().every(fn), false); +assertEq([NaN].values().every(fn), false); +assertEq([-0].values().every(fn), false); +assertEq([0n].values().every(fn), false); + +const htmlDDA = createIsHTMLDDA(); +assertEq([htmlDDA].values().every(fn), false); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/every/descriptor.js b/js/src/tests/non262/Iterator/prototype/every/descriptor.js new file mode 100644 index 0000000000..e11eca28f3 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/every/descriptor.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + Descriptor property of Iterator.prototype.every +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(Iterator.prototype, 'every'); +assertEq(typeof propDesc.value, 'function'); +assertEq(propDesc.writable, true); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/every/error-from-correct-realm.js b/js/src/tests/non262/Iterator/prototype/every/error-from-correct-realm.js new file mode 100644 index 0000000000..7b24a631bb --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/every/error-from-correct-realm.js @@ -0,0 +1,16 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const otherGlobal = newGlobal({newCompartment: true}); +assertEq(TypeError !== otherGlobal.TypeError, true); + +const iter = [].values(); + +assertThrowsInstanceOf(() => iter.every(), TypeError); +assertThrowsInstanceOf( + otherGlobal.Iterator.prototype.every.bind(iter), + otherGlobal.TypeError, + 'TypeError comes from the realm of the method.', +); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/every/fn-not-callable-throws.js b/js/src/tests/non262/Iterator/prototype/every/fn-not-callable-throws.js new file mode 100644 index 0000000000..6b4328180c --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/every/fn-not-callable-throws.js @@ -0,0 +1,15 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const iter = [].values(); + +assertThrowsInstanceOf(() => iter.every(), TypeError); +assertThrowsInstanceOf(() => iter.every(undefined), TypeError); +assertThrowsInstanceOf(() => iter.every(null), TypeError); +assertThrowsInstanceOf(() => iter.every(0), TypeError); +assertThrowsInstanceOf(() => iter.every(false), TypeError); +assertThrowsInstanceOf(() => iter.every(''), TypeError); +assertThrowsInstanceOf(() => iter.every(Symbol('')), TypeError); +assertThrowsInstanceOf(() => iter.every({}), TypeError); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/every/fn-throws-close-iterator.js b/js/src/tests/non262/Iterator/prototype/every/fn-throws-close-iterator.js new file mode 100644 index 0000000000..e3df75e2df --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/every/fn-throws-close-iterator.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +class TestIterator extends Iterator { + next() { + return { done: this.closed }; + } + + closed = false; + return() { + this.closed = true; + } +} + +const fn = () => { throw new Error(); }; +const iter = new TestIterator(); + +assertEq(iter.closed, false); +assertThrowsInstanceOf(() => iter.every(fn), Error); +assertEq(iter.closed, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/every/length.js b/js/src/tests/non262/Iterator/prototype/every/length.js new file mode 100644 index 0000000000..8ef8ecbc7f --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/every/length.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + The `length` property of Iterator.prototype.every. +info: | + ES7 section 17: Unless otherwise specified, the length property of a built-in + Function object has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(Iterator.prototype.every, 'length'); +assertEq(propDesc.value, 1); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/every/name.js b/js/src/tests/non262/Iterator/prototype/every/name.js new file mode 100644 index 0000000000..7a75da9771 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/every/name.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + `name` property of Iterator.prototype.every. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(Iterator.prototype.every, 'name'); +assertEq(propDesc.value, 'every'); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/every/next-throws-iterator-not-closed.js b/js/src/tests/non262/Iterator/prototype/every/next-throws-iterator-not-closed.js new file mode 100644 index 0000000000..56a3dae169 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/every/next-throws-iterator-not-closed.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +class TestIterator extends Iterator { + next() { + throw new Error(); + } + + closed = false; + return() { + this.closed = true; + } +} + +const fn = () => {}; +const iter = new TestIterator(); + +assertEq(iter.closed, false); +assertThrowsInstanceOf(() => iter.every(fn), Error); +assertEq(iter.closed, false); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/every/proxy.js b/js/src/tests/non262/Iterator/prototype/every/proxy.js new file mode 100644 index 0000000000..c3a5b27770 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/every/proxy.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +// +// This test checks that %Iterator.prototype%.every only gets the `next` method off of the +// iterator once, and never accesses the @@iterator property. +const log = []; +const handlerProxy = new Proxy({}, { + get: (target, key, receiver) => (...args) => { + log.push(`${key}: ${args[1]?.toString()}`); + return Reflect[key](...args); + }, +}); + +class Counter extends Iterator { + value = 0; + next() { + const value = this.value; + if (value < 2) { + this.value = value + 1; + return {done: false, value}; + } + return {done: true}; + } +} + +const iter = new Proxy(new Counter(), handlerProxy); +assertEq(iter.every(x => x % 2 == 0), false); + +assertEq( + log.join('\n'), + `get: every +get: next +get: value +set: value +getOwnPropertyDescriptor: value +defineProperty: value +get: value +set: value +getOwnPropertyDescriptor: value +defineProperty: value +get: return` +); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/every/return-true-if-all-match.js b/js/src/tests/non262/Iterator/prototype/every/return-true-if-all-match.js new file mode 100644 index 0000000000..894219d29e --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/every/return-true-if-all-match.js @@ -0,0 +1,11 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const iter = [1, 3, 5].values(); +const fn = (value) => value % 2 == 1; + +assertEq(iter.every(fn), true); + +assertEq([].values().every(x => x), true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/every/short-circuit-on-false.js b/js/src/tests/non262/Iterator/prototype/every/short-circuit-on-false.js new file mode 100644 index 0000000000..15b144a4a4 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/every/short-circuit-on-false.js @@ -0,0 +1,14 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const iter = [1, 2, 3].values(); +const log = []; +const fn = (value) => { + log.push(value.toString()); + return value % 2 == 1; +}; + +assertEq(iter.every(fn), false); +assertEq(log.join(','), '1,2'); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/every/this-not-iterator-throws.js b/js/src/tests/non262/Iterator/prototype/every/this-not-iterator-throws.js new file mode 100644 index 0000000000..5796c8524e --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/every/this-not-iterator-throws.js @@ -0,0 +1,9 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const fn = x => x; +assertThrowsInstanceOf(Iterator.prototype.every.bind(undefined, fn), TypeError); +assertThrowsInstanceOf(Iterator.prototype.every.bind({}, fn), TypeError); +assertThrowsInstanceOf(Iterator.prototype.every.bind({next: 0}, fn), TypeError); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/every/value-throws-iterator-not-closed.js b/js/src/tests/non262/Iterator/prototype/every/value-throws-iterator-not-closed.js new file mode 100644 index 0000000000..61fe29b7a1 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/every/value-throws-iterator-not-closed.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +class TestError extends Error {} +class TestIterator extends Iterator { + next() { + return new Proxy({done: false}, {get: (target, key, receiver) => { + if (key === 'value') + throw new TestError(); + return 0; + }}); + } + + closed = false; + return() { + closed = true; + } +} + +const iterator = new TestIterator(); +assertEq(iterator.closed, false, 'iterator starts unclosed'); +assertThrowsInstanceOf(() => iterator.every(x => x), TestError); +assertEq(iterator.closed, false, 'iterator remains unclosed'); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/filter/coerce-result-to-boolean.js b/js/src/tests/non262/Iterator/prototype/filter/coerce-result-to-boolean.js new file mode 100644 index 0000000000..a3d16bcdfa --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/filter/coerce-result-to-boolean.js @@ -0,0 +1,16 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +// All truthy values are kept. +const truthyValues = [true, 1, [], {}, 'test']; +for (const value of [...truthyValues].values().filter(x => x)) { + assertEq(truthyValues.shift(), value); +} + +// All falsy values are filtered out. +const falsyValues = [false, 0, '', null, undefined, NaN, -0, 0n, createIsHTMLDDA()]; +const result = falsyValues.values().filter(x => x).next(); +assertEq(result.done, true); +assertEq(result.value, undefined); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/filter/filter.js b/js/src/tests/non262/Iterator/prototype/filter/filter.js new file mode 100644 index 0000000000..1d148cb82b --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/filter/filter.js @@ -0,0 +1,14 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +let iter = [1, 2, 3].values().filter(x => x % 2); + +for (const v of [1, 3]) { + let result = iter.next(); + assertEq(result.done, false); + assertEq(result.value, v); +} + +assertEq(iter.next().done, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/filter/length.js b/js/src/tests/non262/Iterator/prototype/filter/length.js new file mode 100644 index 0000000000..c1fad91b1d --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/filter/length.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) +// + +/*--- +esid: pending +description: %Iterator.prototype%.filter length value and descriptor. +info: > + 17 ECMAScript Standard Built-in Objects +includes: [propertyHelper.js] +features: [Symbol.iterator] +---*/ + +assertEq(Iterator.prototype.filter.length, 1); + +const propertyDescriptor = Reflect.getOwnPropertyDescriptor(Iterator.prototype.filter, 'length'); +assertEq(propertyDescriptor.value, 1); +assertEq(propertyDescriptor.enumerable, false); +assertEq(propertyDescriptor.writable, false); +assertEq(propertyDescriptor.configurable, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/filter/name.js b/js/src/tests/non262/Iterator/prototype/filter/name.js new file mode 100644 index 0000000000..b278220225 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/filter/name.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) +/*--- +esid: pending +description: %Iterator.prototype%.filter.name value and descriptor. +info: > + 17 ECMAScript Standard Built-in Objects +features: [iterator-helpers] +---*/ + +assertEq(Iterator.prototype.filter.name, 'filter'); + +const propertyDescriptor = Reflect.getOwnPropertyDescriptor(Iterator.prototype.filter, 'name'); +assertEq(propertyDescriptor.value, 'filter'); +assertEq(propertyDescriptor.enumerable, false); +assertEq(propertyDescriptor.writable, false); +assertEq(propertyDescriptor.configurable, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/find/check-fn-after-getting-iterator.js b/js/src/tests/non262/Iterator/prototype/find/check-fn-after-getting-iterator.js new file mode 100644 index 0000000000..3a5396d62b --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/find/check-fn-after-getting-iterator.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +const log = []; +const handlerProxy = new Proxy({}, { + get: (target, key, receiver) => (...args) => { + log.push(`${key}: ${args[1]?.toString()}`); + return Reflect[key](...args); + }, +}); + +class TestIterator extends Iterator { + next() { + return {done: true}; + } +} + +const iter = new Proxy(new TestIterator(), handlerProxy); +assertThrowsInstanceOf(() => iter.find(1), TypeError); + +assertEqArray( + log, + ["get: find"] +); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/find/coerce-result-to-boolean.js b/js/src/tests/non262/Iterator/prototype/find/coerce-result-to-boolean.js new file mode 100644 index 0000000000..7818e5a58d --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/find/coerce-result-to-boolean.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const fn = (value) => value; +assertEq([true].values().find(fn), true); +assertEq([1].values().find(fn), 1); +assertEq(['test'].values().find(fn), 'test'); + +assertEq([false].values().find(fn), undefined); +assertEq([0].values().find(fn), undefined); +assertEq([''].values().find(fn), undefined); +assertEq([null].values().find(fn), undefined); +assertEq([undefined].values().find(fn), undefined); +assertEq([NaN].values().find(fn), undefined); +assertEq([-0].values().find(fn), undefined); +assertEq([0n].values().find(fn), undefined); + +let array = []; +assertEq([array].values().find(fn), array); + +let object = {}; +assertEq([object].values().find(fn), object); + +const htmlDDA = createIsHTMLDDA(); +assertEq([htmlDDA].values().find(fn), undefined); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/find/descriptor.js b/js/src/tests/non262/Iterator/prototype/find/descriptor.js new file mode 100644 index 0000000000..45699dff85 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/find/descriptor.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + Descriptor property of Iterator.prototype.find +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(Iterator.prototype, 'find'); +assertEq(typeof propDesc.value, 'function'); +assertEq(propDesc.writable, true); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/find/error-from-correct-realm.js b/js/src/tests/non262/Iterator/prototype/find/error-from-correct-realm.js new file mode 100644 index 0000000000..b34408e853 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/find/error-from-correct-realm.js @@ -0,0 +1,16 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const otherGlobal = newGlobal({newCompartment: true}); +assertEq(TypeError !== otherGlobal.TypeError, true); + +const iter = [].values(); + +assertThrowsInstanceOf(() => iter.find(), TypeError); +assertThrowsInstanceOf( + otherGlobal.Iterator.prototype.find.bind(iter), + otherGlobal.TypeError, + 'TypeError comes from the realm of the method.', +); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/find/fn-not-callable-throws.js b/js/src/tests/non262/Iterator/prototype/find/fn-not-callable-throws.js new file mode 100644 index 0000000000..33d18b49cc --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/find/fn-not-callable-throws.js @@ -0,0 +1,15 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const iter = [].values(); + +assertThrowsInstanceOf(() => iter.find(), TypeError); +assertThrowsInstanceOf(() => iter.find(undefined), TypeError); +assertThrowsInstanceOf(() => iter.find(null), TypeError); +assertThrowsInstanceOf(() => iter.find(0), TypeError); +assertThrowsInstanceOf(() => iter.find(false), TypeError); +assertThrowsInstanceOf(() => iter.find(''), TypeError); +assertThrowsInstanceOf(() => iter.find(Symbol('')), TypeError); +assertThrowsInstanceOf(() => iter.find({}), TypeError); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/find/fn-throws-close-iterator.js b/js/src/tests/non262/Iterator/prototype/find/fn-throws-close-iterator.js new file mode 100644 index 0000000000..1393bee356 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/find/fn-throws-close-iterator.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +class TestIterator extends Iterator { + next() { + return { done: this.closed }; + } + + closed = false; + return() { + this.closed = true; + } +} + +const fn = (value) => { throw new Error(); }; +const iter = new TestIterator(); + +assertEq(iter.closed, false); +assertThrowsInstanceOf(() => iter.find(fn), Error); +assertEq(iter.closed, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/find/length.js b/js/src/tests/non262/Iterator/prototype/find/length.js new file mode 100644 index 0000000000..b182ca0e78 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/find/length.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + The `length` property of Iterator.prototype.find. +info: | + ES7 section 17: Unless otherwise specified, the length property of a built-in + Function object has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(Iterator.prototype.find, 'length'); +assertEq(propDesc.value, 1); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/find/name.js b/js/src/tests/non262/Iterator/prototype/find/name.js new file mode 100644 index 0000000000..36d903b44c --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/find/name.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + `name` property of Iterator.prototype.find. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(Iterator.prototype.find, 'name'); +assertEq(propDesc.value, 'find'); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/find/next-throws-iterator-not-closed.js b/js/src/tests/non262/Iterator/prototype/find/next-throws-iterator-not-closed.js new file mode 100644 index 0000000000..13c3195654 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/find/next-throws-iterator-not-closed.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +class TestIterator extends Iterator { + next() { + throw new Error(); + } + + closed = false; + return() { + this.closed = true; + } +} + +const fn = x => x; +const iter = new TestIterator(); + +assertEq(iter.closed, false); +assertThrowsInstanceOf(() => iter.find(fn), Error); +assertEq(iter.closed, false); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/find/proxy.js b/js/src/tests/non262/Iterator/prototype/find/proxy.js new file mode 100644 index 0000000000..c24d787710 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/find/proxy.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +// +// This test checks that %Iterator.prototype%.find only gets the `next` method off of the +// iterator once, and never accesses the @@iterator property. +const log = []; +const handlerProxy = new Proxy({}, { + get: (target, key, receiver) => (...args) => { + log.push(`${key}: ${args[1]?.toString()}`); + return Reflect[key](...args); + }, +}); + +class Counter extends Iterator { + value = 0; + next() { + const value = this.value; + if (value < 2) { + this.value = value + 1; + return {done: false, value}; + } + return {done: true}; + } +} + +const iter = new Proxy(new Counter(), handlerProxy); +assertEq(iter.find(x => x % 2 == 1), 1); + +assertEq( + log.join('\n'), + `get: find +get: next +get: value +set: value +getOwnPropertyDescriptor: value +defineProperty: value +get: value +set: value +getOwnPropertyDescriptor: value +defineProperty: value +get: return` +); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/find/return-undefined-if-none-match.js b/js/src/tests/non262/Iterator/prototype/find/return-undefined-if-none-match.js new file mode 100644 index 0000000000..3e7364fa95 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/find/return-undefined-if-none-match.js @@ -0,0 +1,11 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const iter = [1, 3, 5].values(); +const fn = (value) => value % 2 == 0; + +assertEq(iter.find(fn), undefined); + +assertEq([].values().find(x => x), undefined); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/find/short-circuit-on-match.js b/js/src/tests/non262/Iterator/prototype/find/short-circuit-on-match.js new file mode 100644 index 0000000000..8ce7c5a354 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/find/short-circuit-on-match.js @@ -0,0 +1,14 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const iter = [1, 2, 3].values(); +const log = []; +const fn = (value) => { + log.push(value.toString()); + return value % 2 == 0; +}; + +assertEq(iter.find(fn), 2); +assertEq(log.join(','), '1,2'); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/find/this-not-iterator-throws.js b/js/src/tests/non262/Iterator/prototype/find/this-not-iterator-throws.js new file mode 100644 index 0000000000..8e1d446705 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/find/this-not-iterator-throws.js @@ -0,0 +1,9 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const fn = x => x; +assertThrowsInstanceOf(Iterator.prototype.find.bind(undefined, fn), TypeError); +assertThrowsInstanceOf(Iterator.prototype.find.bind({}, fn), TypeError); +assertThrowsInstanceOf(Iterator.prototype.find.bind({next: 0}, fn), TypeError); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/find/value-throws-iterator-not-closed.js b/js/src/tests/non262/Iterator/prototype/find/value-throws-iterator-not-closed.js new file mode 100644 index 0000000000..23873c618a --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/find/value-throws-iterator-not-closed.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +class TestError extends Error {} +class TestIterator extends Iterator { + next() { + return new Proxy({done: false}, {get: (target, key, receiver) => { + if (key === 'value') + throw new TestError(); + return 0; + }}); + } + + closed = false; + return() { + closed = true; + } +} + +const iterator = new TestIterator(); +assertEq(iterator.closed, false, 'iterator starts unclosed'); +assertThrowsInstanceOf(() => iterator.find(x => x), TestError); +assertEq(iterator.closed, false, 'iterator remains unclosed'); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/flatMap/close-iterator-when-inner-complete-throws.js b/js/src/tests/non262/Iterator/prototype/flatMap/close-iterator-when-inner-complete-throws.js new file mode 100644 index 0000000000..3a0bfcf167 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/flatMap/close-iterator-when-inner-complete-throws.js @@ -0,0 +1,49 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +// +// +/*--- +esid: pending +description: %Iterator.prototype%.flatMap closes the iterator when innerComplete throws. +info: > + Iterator Helpers proposal 2.1.5.7 + 1. Repeat, + ... + i. Repeat, while innerAlive is true, + iii. Let innerComplete be IteratorComplete(innerNext). + iv. IfAbruptCloseIterator(innerComplete, iterated). +features: [iterator-helpers] +---*/ + +class TestIterator extends Iterator { + next() { + return {done: false, value: 0}; + } + + closed = false; + return() { + this.closed = true; + return {done: true}; + } +} + +class TestError extends Error {} +class InnerIterator extends Iterator { + next() { + return { + get done() { + throw new TestError(); + } + }; + } +} + +const iter = new TestIterator(); +const mapped = iter.flatMap(x => new InnerIterator()); + +assertEq(iter.closed, false); +assertThrowsInstanceOf(() => mapped.next(), TestError); +assertEq(iter.closed, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/flatMap/close-iterator-when-inner-next-throws.js b/js/src/tests/non262/Iterator/prototype/flatMap/close-iterator-when-inner-next-throws.js new file mode 100644 index 0000000000..a8f70497f7 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/flatMap/close-iterator-when-inner-next-throws.js @@ -0,0 +1,45 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +// +// +/*--- +esid: pending +description: %Iterator.prototype%.flatMap closes the iterator when innerNext throws. +info: > + Iterator Helpers proposal 2.1.5.7 + 1. Repeat, + ... + i. Repeat, while innerAlive is true, + i. Let innerNext be IteratorNext(innerIterator). + ii. IfAbruptCloseIterator(innerNext, iterated). +features: [iterator-helpers] +---*/ + +class TestIterator extends Iterator { + next() { + return {done: false, value: 0}; + } + + closed = false; + return() { + this.closed = true; + return {done: true}; + } +} + +class TestError extends Error {} +class InnerIterator extends Iterator { + next() { + throw new TestError(); + } +} + +const iter = new TestIterator(); +const mapped = iter.flatMap(x => new InnerIterator()); + +assertEq(iter.closed, false); +assertThrowsInstanceOf(() => mapped.next(), TestError); +assertEq(iter.closed, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/flatMap/close-iterator-when-inner-value-throws.js b/js/src/tests/non262/Iterator/prototype/flatMap/close-iterator-when-inner-value-throws.js new file mode 100644 index 0000000000..3b2f26b401 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/flatMap/close-iterator-when-inner-value-throws.js @@ -0,0 +1,52 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +// +// +/*--- +esid: pending +description: %Iterator.prototype%.flatMap closes the iterator when innerValue throws. +info: > + Iterator Helpers proposal 2.1.5.7 + 1. Repeat, + ... + i. Repeat, while innerAlive is true, + ... + vi. Else, + 1. Let innerValue be IteratorValue(innerNext). + 2. IfAbruptCloseIterator(innerValue, iterated). +features: [iterator-helpers] +---*/ + +class TestIterator extends Iterator { + next() { + return {done: false, value: 0}; + } + + closed = false; + return() { + this.closed = true; + return {done: true}; + } +} + +class TestError extends Error {} +class InnerIterator extends Iterator { + next() { + return { + done: false, + get value() { + throw new TestError(); + }, + }; + } +} + +const iter = new TestIterator(); +const mapped = iter.flatMap(x => new InnerIterator()); + +assertEq(iter.closed, false); +assertThrowsInstanceOf(() => mapped.next(), TestError); +assertEq(iter.closed, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/flatMap/flatMap.js b/js/src/tests/non262/Iterator/prototype/flatMap/flatMap.js new file mode 100644 index 0000000000..6acce22593 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/flatMap/flatMap.js @@ -0,0 +1,12 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +let iter = [1, 2, 3].values().flatMap(x => [x, x + 1]); +for (const v of [1, 2, 2, 3, 3, 4]) { + let result = iter.next(); + assertEq(result.done, false); + assertEq(result.value, v); +} +assertEq(iter.next().done, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/flatMap/inner-empty-iterable.js b/js/src/tests/non262/Iterator/prototype/flatMap/inner-empty-iterable.js new file mode 100644 index 0000000000..24fcc85c2c --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/flatMap/inner-empty-iterable.js @@ -0,0 +1,38 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +// +// +/*--- +esid: pending +description: %Iterator.prototype%.flatMap skips empty inner iterables. +info: > + Iterator Helpers proposal 2.1.5.7 + 1. Repeat, + ... + i. Repeat, while innerAlive is true, + ... + iii. Let innerComplete be IteratorComplete(innerNext). + ... + v. If innerComplete is true, set innerAlive to false. +features: [iterator-helpers] +---*/ + +let iter = [0, 1, 2, 3].values().flatMap(x => x % 2 ? [] : [x]); + +for (const expected of [0, 2]) { + const result = iter.next(); + assertEq(result.value, expected); + assertEq(result.done, false); +} + +let result = iter.next(); +assertEq(result.value, undefined); +assertEq(result.done, true); + +iter = [0, 1, 2, 3].values().flatMap(x => []); +result = iter.next(); +assertEq(result.value, undefined); +assertEq(result.done, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/flatMap/inner-generator.js b/js/src/tests/non262/Iterator/prototype/flatMap/inner-generator.js new file mode 100644 index 0000000000..9589027b4b --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/flatMap/inner-generator.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +// +// +/*--- +esid: pending +description: %Iterator.prototype%.flatMap innerIterator can be a generator. +info: > + Iterator Helpers proposal 2.1.5.7 +features: [iterator-helpers] +---*/ + +const iter = [1, 2].values().flatMap(function*(x) { + yield x; + yield* [x + 1, x + 2]; +}); + +for (const expected of [1, 2, 3, 2, 3, 4]) { + const result = iter.next(); + assertEq(result.value, expected); + assertEq(result.done, false); +} + +const result = iter.next(); +assertEq(result.value, undefined); +assertEq(result.done, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/flatMap/length.js b/js/src/tests/non262/Iterator/prototype/flatMap/length.js new file mode 100644 index 0000000000..d5f8a5021f --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/flatMap/length.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) +// + +/*--- +esid: pending +description: %Iterator.prototype%.flatMap length value and descriptor. +info: > + 17 ECMAScript Standard Built-in Objects +includes: [propertyHelper.js] +features: [Symbol.iterator] +---*/ + +assertEq(Iterator.prototype.flatMap.length, 1); + +const propertyDescriptor = Reflect.getOwnPropertyDescriptor(Iterator.prototype.flatMap, 'length'); +assertEq(propertyDescriptor.value, 1); +assertEq(propertyDescriptor.enumerable, false); +assertEq(propertyDescriptor.writable, false); +assertEq(propertyDescriptor.configurable, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/flatMap/name.js b/js/src/tests/non262/Iterator/prototype/flatMap/name.js new file mode 100644 index 0000000000..6cc6b98ef0 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/flatMap/name.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) +/*--- +esid: pending +description: %Iterator.prototype%.flatMap.name value and descriptor. +info: > + 17 ECMAScript Standard Built-in Objects +features: [iterator-helpers] +---*/ + +assertEq(Iterator.prototype.flatMap.name, 'flatMap'); + +const propertyDescriptor = Reflect.getOwnPropertyDescriptor(Iterator.prototype.flatMap, 'name'); +assertEq(propertyDescriptor.value, 'flatMap'); +assertEq(propertyDescriptor.enumerable, false); +assertEq(propertyDescriptor.writable, false); +assertEq(propertyDescriptor.configurable, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/flatMap/throw-when-inner-not-iterable.js b/js/src/tests/non262/Iterator/prototype/flatMap/throw-when-inner-not-iterable.js new file mode 100644 index 0000000000..55e691f1d8 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/flatMap/throw-when-inner-not-iterable.js @@ -0,0 +1,57 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +// +// +/*--- +esid: pending +description: %Iterator.prototype%.flatMap closes the iterator and throws when mapped isn't iterable. +info: > + Iterator Helpers proposal 2.1.5.7 + 1. Repeat, + ... + f. Let innerIterator be GetIteratorFlattenable(mapped). + g. IfAbruptCloseIterator(innerIterator, iterated). +features: [iterator-helpers] +---*/ + +class InvalidIterable { + [Symbol.iterator]() { + return {}; + } +} + +class TestIterator extends Iterator { + next() { + return {done: false, value: 0}; + } + + closed = false; + return() { + this.closed = true; + return {done: true}; + } +} + +const nonIterables = [ + new InvalidIterable(), + undefined, + null, + 0, + false, + Symbol(''), + 0n, + {}, +]; + +for (const value of nonIterables) { + const iter = new TestIterator(); + const mapped = iter.flatMap(x => value); + + assertEq(iter.closed, false); + assertThrowsInstanceOf(() => mapped.next(), TypeError); + assertEq(iter.closed, true); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); + diff --git a/js/src/tests/non262/Iterator/prototype/forEach/check-fn-after-getting-iterator.js b/js/src/tests/non262/Iterator/prototype/forEach/check-fn-after-getting-iterator.js new file mode 100644 index 0000000000..ed4f7b416c --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/forEach/check-fn-after-getting-iterator.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +const log = []; +const handlerProxy = new Proxy({}, { + get: (target, key, receiver) => (...args) => { + log.push(`${key}: ${args[1]?.toString()}`); + return Reflect[key](...args); + }, +}); + +class TestIterator extends Iterator { + next() { + return {done: true}; + } +} + +const iter = new Proxy(new TestIterator(), handlerProxy); +assertThrowsInstanceOf(() => iter.forEach(1), TypeError); + +assertEqArray( + log, + ["get: forEach"] +); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/forEach/descriptor.js b/js/src/tests/non262/Iterator/prototype/forEach/descriptor.js new file mode 100644 index 0000000000..b33be1e435 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/forEach/descriptor.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + Descriptor property of Iterator.prototype.forEach +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(Iterator.prototype, 'forEach'); +assertEq(typeof propDesc.value, 'function'); +assertEq(propDesc.writable, true); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/forEach/error-from-correct-realm.js b/js/src/tests/non262/Iterator/prototype/forEach/error-from-correct-realm.js new file mode 100644 index 0000000000..38c8e9bb5c --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/forEach/error-from-correct-realm.js @@ -0,0 +1,16 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const otherGlobal = newGlobal({newCompartment: true}); +assertEq(TypeError !== otherGlobal.TypeError, true); + +const iter = [].values(); + +assertThrowsInstanceOf(() => iter.forEach(), TypeError); +assertThrowsInstanceOf( + otherGlobal.Iterator.prototype.forEach.bind(iter), + otherGlobal.TypeError, + 'TypeError comes from the realm of the method.', +); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/forEach/fn-not-callable-throws.js b/js/src/tests/non262/Iterator/prototype/forEach/fn-not-callable-throws.js new file mode 100644 index 0000000000..473789a6a2 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/forEach/fn-not-callable-throws.js @@ -0,0 +1,15 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const iter = [].values(); + +assertThrowsInstanceOf(() => iter.forEach(), TypeError); +assertThrowsInstanceOf(() => iter.forEach(undefined), TypeError); +assertThrowsInstanceOf(() => iter.forEach(null), TypeError); +assertThrowsInstanceOf(() => iter.forEach(0), TypeError); +assertThrowsInstanceOf(() => iter.forEach(false), TypeError); +assertThrowsInstanceOf(() => iter.forEach(''), TypeError); +assertThrowsInstanceOf(() => iter.forEach(Symbol('')), TypeError); +assertThrowsInstanceOf(() => iter.forEach({}), TypeError); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/forEach/fn-throws-close-iterator.js b/js/src/tests/non262/Iterator/prototype/forEach/fn-throws-close-iterator.js new file mode 100644 index 0000000000..1703673f0d --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/forEach/fn-throws-close-iterator.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +class TestIterator extends Iterator { + next() { + return { done: this.closed }; + } + + closed = false; + return() { + this.closed = true; + } +} + +const fn = () => { throw new Error(); }; +const iter = new TestIterator(); + +assertEq(iter.closed, false); +assertThrowsInstanceOf(() => iter.forEach(fn), Error); +assertEq(iter.closed, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/forEach/forEach.js b/js/src/tests/non262/Iterator/prototype/forEach/forEach.js new file mode 100644 index 0000000000..62ddce6eb7 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/forEach/forEach.js @@ -0,0 +1,11 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const log = []; +const fn = (value) => log.push(value); +const iter = [1, 2, 3].values(); + +assertEq(iter.forEach(fn), undefined); +assertEq(log.join(','), '1,2,3'); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/forEach/length.js b/js/src/tests/non262/Iterator/prototype/forEach/length.js new file mode 100644 index 0000000000..9f2f9134f8 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/forEach/length.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + The `length` property of Iterator.prototype.forEach. +info: | + ES7 section 17: Unless otherwise specified, the length property of a built-in + Function object has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(Iterator.prototype.forEach, 'length'); +assertEq(propDesc.value, 1); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/forEach/name.js b/js/src/tests/non262/Iterator/prototype/forEach/name.js new file mode 100644 index 0000000000..7c4964e696 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/forEach/name.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + `name` property of Iterator.prototype.forEach. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(Iterator.prototype.forEach, 'name'); +assertEq(propDesc.value, 'forEach'); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/forEach/next-throws-iterator-not-closed.js b/js/src/tests/non262/Iterator/prototype/forEach/next-throws-iterator-not-closed.js new file mode 100644 index 0000000000..042b6d660c --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/forEach/next-throws-iterator-not-closed.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +class TestIterator extends Iterator { + next() { + throw new Error(); + } + + closed = false; + return() { + this.closed = true; + } +} + +const fn = () => {}; +const iter = new TestIterator(); + +assertEq(iter.closed, false); +assertThrowsInstanceOf(() => iter.forEach(fn), Error); +assertEq(iter.closed, false); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/forEach/proxy.js b/js/src/tests/non262/Iterator/prototype/forEach/proxy.js new file mode 100644 index 0000000000..9d50aed9fe --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/forEach/proxy.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +// +// This test checks that %Iterator.prototype%.forEach only gets the `next` method off of the +// iterator once, and never accesses the @@iterator property. +const log = []; +const handlerProxy = new Proxy({}, { + get: (target, key, receiver) => (...args) => { + log.push(`${key}: ${args[1]?.toString()}`); + return Reflect[key](...args); + }, +}); + +class Counter extends Iterator { + value = 0; + next() { + const value = this.value; + if (value < 2) { + this.value = value + 1; + return {done: false, value}; + } + return {done: true}; + } +} + +const iter = new Proxy(new Counter(), handlerProxy); +iter.forEach(x => x); + +assertEq( + log.join('\n'), + `get: forEach +get: next +get: value +set: value +getOwnPropertyDescriptor: value +defineProperty: value +get: value +set: value +getOwnPropertyDescriptor: value +defineProperty: value +get: value` +); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/forEach/this-not-iterator-throws.js b/js/src/tests/non262/Iterator/prototype/forEach/this-not-iterator-throws.js new file mode 100644 index 0000000000..d47ba38960 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/forEach/this-not-iterator-throws.js @@ -0,0 +1,9 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const fn = x => x; +assertThrowsInstanceOf(Iterator.prototype.forEach.bind(undefined, fn), TypeError); +assertThrowsInstanceOf(Iterator.prototype.forEach.bind({}, fn), TypeError); +assertThrowsInstanceOf(Iterator.prototype.forEach.bind({next: 0}, fn), TypeError); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/forEach/value-throws-iterator-not-closed.js b/js/src/tests/non262/Iterator/prototype/forEach/value-throws-iterator-not-closed.js new file mode 100644 index 0000000000..28f1d64113 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/forEach/value-throws-iterator-not-closed.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +class TestError extends Error {} +class TestIterator extends Iterator { + next() { + return new Proxy({done: false}, {get: (target, key, receiver) => { + if (key === 'value') + throw new TestError(); + return 0; + }}); + } + + closed = false; + return() { + closed = true; + } +} + +const iterator = new TestIterator(); +assertEq(iterator.closed, false, 'iterator starts unclosed'); +assertThrowsInstanceOf(() => iterator.forEach(x => x), TestError); +assertEq(iterator.closed, false, 'iterator remains unclosed'); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/generator-methods-throw-on-iterator-helpers.js b/js/src/tests/non262/Iterator/prototype/generator-methods-throw-on-iterator-helpers.js new file mode 100644 index 0000000000..f684be43fb --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/generator-methods-throw-on-iterator-helpers.js @@ -0,0 +1,16 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +const generatorProto = Object.getPrototypeOf( + Object.getPrototypeOf( + (function *() {})() + ) +); + +const iteratorHelper = [0].values().map(x => x); + +assertThrowsInstanceOf(() => generatorProto.next.call(iteratorHelper), TypeError); +assertThrowsInstanceOf(() => generatorProto.return.call(iteratorHelper), TypeError); +assertThrowsInstanceOf(() => generatorProto.throw.call(iteratorHelper), TypeError); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/iterator-helper-methods-throw-on-generators.js b/js/src/tests/non262/Iterator/prototype/iterator-helper-methods-throw-on-generators.js new file mode 100644 index 0000000000..e074d7e580 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/iterator-helper-methods-throw-on-generators.js @@ -0,0 +1,14 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +const iteratorHelperProto = Object.getPrototypeOf([].values().map(x => x)); + +function *gen() { + yield 1; +} + +assertThrowsInstanceOf(() => iteratorHelperProto.next.call(gen()), TypeError); +assertThrowsInstanceOf(() => iteratorHelperProto.return.call(gen()), TypeError); +assertThrowsInstanceOf(() => iteratorHelperProto.throw.call(gen()), TypeError); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/iterator-helpers-from-other-global.js b/js/src/tests/non262/Iterator/prototype/iterator-helpers-from-other-global.js new file mode 100644 index 0000000000..c567ddda64 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/iterator-helpers-from-other-global.js @@ -0,0 +1,53 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +class TestError extends Error {} + +class TestIterator extends Iterator { + next() { + return {done: false, value: 'value'}; + } + + closed = false; + return(value) { + this.closed = true; + return {done: true, value}; + } +} + +function checkIterResult({done, value}, expectedDone, expectedValue) { + assertEq(done, expectedDone); + assertEq(Array.isArray(value) ? value[1] : value, expectedValue); +} + +const otherGlobal = newGlobal({newCompartment: true}); + +const methods = [ + ["map", x => x], + ["filter", x => true], + ["take", Infinity], + ["drop", 0], + ["flatMap", x => [x]], +]; + +for (const [method, arg] of methods) { + const {next: otherNext} = Object.getPrototypeOf( + new otherGlobal.Array().values()[method](arg) + ); + const iterator = new TestIterator(); + const helper = iterator[method](arg); + checkIterResult(otherNext.call(helper), false, 'value'); +} + +for (const [method, arg] of methods) { + const {return: otherReturn} = Object.getPrototypeOf( + new otherGlobal.Array().values()[method](arg) + ); + const iterator = new TestIterator(); + const helper = iterator[method](arg); + assertEq(iterator.closed, false); + checkIterResult(otherReturn.call(helper), true, undefined); + assertEq(iterator.closed, true); +} + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/lazy-methods-from-other-global.js b/js/src/tests/non262/Iterator/prototype/lazy-methods-from-other-global.js new file mode 100644 index 0000000000..720baf08c7 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/lazy-methods-from-other-global.js @@ -0,0 +1,30 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +const otherIteratorProto = newGlobal({newCompartment: true}).Iterator.prototype; + +const methods = [ + ["map", x => x], + ["filter", x => true], + ["take", Infinity], + ["drop", 0], + ["flatMap", x => [x]], +]; + +// Use the lazy Iterator methods from another global on an iterator from this global. +for (const [method, arg] of methods) { + const iterator = [1, 2, 3].values(); + const helper = otherIteratorProto[method].call(iterator, arg); + + for (const expected of [1, 2, 3]) { + const {done, value} = helper.next(); + assertEq(done, false); + assertEq(Array.isArray(value) ? value[1] : value, expected); + } + + const {done, value} = helper.next(); + assertEq(done, true); + assertEq(value, undefined); +} + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/lazy-methods-handle-empty-iterators.js b/js/src/tests/non262/Iterator/prototype/lazy-methods-handle-empty-iterators.js new file mode 100644 index 0000000000..58ee3070bc --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/lazy-methods-handle-empty-iterators.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +// +// +/*--- +esid: pending +description: Lazy %Iterator.prototype% methods handle empty iterators. +info: > + Iterator Helpers proposal 2.1.5 +features: [iterator-helpers] +---*/ + +class EmptyIterator extends Iterator { + next() { + return {done: true}; + } +} + +const emptyIterator1 = new EmptyIterator(); +const emptyIterator2 = [].values(); + +const methods = [ + iter => iter.map(x => x), + iter => iter.filter(x => x), + iter => iter.take(1), + iter => iter.drop(0), + iter => iter.flatMap(x => [x]), +]; + +for (const method of methods) { + for (const iterator of [emptyIterator1, emptyIterator2]) { + const result = method(iterator).next(); + assertEq(result.done, true); + assertEq(result.value, undefined); + } +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/lazy-methods-interleaved.js b/js/src/tests/non262/Iterator/prototype/lazy-methods-interleaved.js new file mode 100644 index 0000000000..9a79ad5fd5 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/lazy-methods-interleaved.js @@ -0,0 +1,57 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +// +// +/*--- +esid: pending +description: Lazy %Iterator.prototype% method calls can be interleaved. +info: > + Iterator Helpers proposal 2.1.5 +features: [iterator-helpers] +---*/ + +class TestIterator extends Iterator { + value = 0; + next() { + return {done: false, value: this.value++}; + } +} + +function unwrapResult(result) { + return result; +} + +const methods = [ + iter => iter.map(x => x), + iter => iter.filter(x => true), + iter => iter.take(2), + iter => iter.drop(0), + iter => iter.flatMap(x => [x]), +]; + +for (const firstMethod of methods) { + for (const secondMethod of methods) { + const iterator = new TestIterator(); + const firstHelper = firstMethod(iterator); + const secondHelper = secondMethod(iterator); + + let firstResult = unwrapResult(firstHelper.next()); + assertEq(firstResult.done, false); + assertEq(firstResult.value, 0); + + let secondResult = unwrapResult(secondHelper.next()); + assertEq(secondResult.done, false); + assertEq(secondResult.value, 1); + + firstResult = unwrapResult(firstHelper.next()); + assertEq(firstResult.done, false); + assertEq(firstResult.value, 2); + + secondResult = unwrapResult(secondHelper.next()); + assertEq(secondResult.done, false); + assertEq(secondResult.value, 3); + } +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/lazy-methods-iterator-closed-on-call-throws.js b/js/src/tests/non262/Iterator/prototype/lazy-methods-iterator-closed-on-call-throws.js new file mode 100644 index 0000000000..f81e9280ce --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/lazy-methods-iterator-closed-on-call-throws.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +// +// +/*--- +esid: pending +description: Lazy %Iterator.prototype% methods close the iterator if callback throws. +info: > + Iterator Helpers proposal 2.1.5 +features: [iterator-helpers] +---*/ + +class TestError extends Error {} +class TestIterator extends Iterator { + next() { + return {done: false, value: 1}; + } + + closed = false; + return() { + this.closed = true; + return {done: true}; + } +} + +function fn() { + throw new TestError(); +} +const methods = [ + iter => iter.map(fn), + iter => iter.filter(fn), + iter => iter.flatMap(fn), +]; + +for (const method of methods) { + const iter = new TestIterator(); + assertEq(iter.closed, false); + assertThrowsInstanceOf(() => method(iter).next(), TestError); + assertEq(iter.closed, true); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); + diff --git a/js/src/tests/non262/Iterator/prototype/lazy-methods-iterator-closed-on-yield-throws.js b/js/src/tests/non262/Iterator/prototype/lazy-methods-iterator-closed-on-yield-throws.js new file mode 100644 index 0000000000..b878a80c7b --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/lazy-methods-iterator-closed-on-yield-throws.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +// +// +/*--- +esid: pending +description: Lazy %Iterator.prototype% methods close the iterator if `yield` throws. +info: > + Iterator Helpers proposal 2.1.5 +features: [iterator-helpers] +---*/ + +class TestIterator extends Iterator { + next() { + return {done: false, value: 1}; + } + + closed = false; + return() { + this.closed = true; + return {done: true}; + } +} + +const methods = [ + iter => iter.map(x => x), + iter => iter.filter(x => true), + iter => iter.take(1), + iter => iter.drop(0), + iter => iter.flatMap(x => [x]), +]; + +for (const method of methods) { + const iterator = new TestIterator(); + assertEq(iterator.closed, false); + const iteratorHelper = method(iterator); + iteratorHelper.next(); + iteratorHelper.return(); + assertEq(iterator.closed, true); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/lazy-methods-iterator-not-closed-on-next-throws.js b/js/src/tests/non262/Iterator/prototype/lazy-methods-iterator-not-closed-on-next-throws.js new file mode 100644 index 0000000000..ac1051db04 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/lazy-methods-iterator-not-closed-on-next-throws.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +// +// +/*--- +esid: pending +description: Lazy %Iterator.prototype% methods don't close the iterator if `.next` call throws. +info: > + Iterator Helpers proposal 2.1.5 +features: [iterator-helpers] +---*/ + +class TestError extends Error {} +class TestIterator extends Iterator { + next() { + throw new TestError(); + } + + closed = false; + return() { + this.closed = true; + return {done: true}; + } +} + +const iterator = new TestIterator(); + +const methods = [ + iter => iter.map(x => x), + iter => iter.filter(x => x), + iter => iter.take(1), + iter => iter.drop(0), + iter => iter.flatMap(x => [x]), +]; + +for (const method of methods) { + assertEq(iterator.closed, false); + assertThrowsInstanceOf(() => method(iterator).next(), TestError); + assertEq(iterator.closed, false); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/lazy-methods-iterator-not-closed-on-value-throws.js b/js/src/tests/non262/Iterator/prototype/lazy-methods-iterator-not-closed-on-value-throws.js new file mode 100644 index 0000000000..acc80dba90 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/lazy-methods-iterator-not-closed-on-value-throws.js @@ -0,0 +1,47 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +// +// +/*--- +esid: pending +description: Lazy %Iterator.prototype% methods don't close the iterator if `value` throws. +info: > + Iterator Helpers proposal 2.1.5 +features: [iterator-helpers] +---*/ + +class TestError extends Error {} +class TestIterator extends Iterator { + next() { + return { + get value() { + throw new TestError(); + } + }; + } + + closed = false; + return() { + this.closed = true; + return {done: true}; + } +} + +const iterator = new TestIterator(); + +const methods = [ + iter => iter.map(x => x), + iter => iter.filter(x => x), + iter => iter.take(1), + iter => iter.drop(0), + iter => iter.flatMap(x => [x]), +]; + +for (const method of methods) { + assertEq(iterator.closed, false); + assertThrowsInstanceOf(() => method(iterator).next(), TestError); + assertEq(iterator.closed, false); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/lazy-methods-iterator-returns-done-generator-finishes.js b/js/src/tests/non262/Iterator/prototype/lazy-methods-iterator-returns-done-generator-finishes.js new file mode 100644 index 0000000000..f1d5bb4c38 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/lazy-methods-iterator-returns-done-generator-finishes.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +class TestIterator extends Iterator { + next() { + return {done: true, value: 'value'}; + } +} + +const methods = [ + iter => iter.map(x => x), + iter => iter.filter(x => true), + iter => iter.take(1), + iter => iter.drop(0), + iter => iter.flatMap(x => [x]), +]; + +for (const method of methods) { + const iterator = method(new TestIterator()); + const result = iterator.next(); + assertEq(result.done, true); + assertEq(result.value, undefined); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); + diff --git a/js/src/tests/non262/Iterator/prototype/lazy-methods-multiple-return-close-iterator-once.js b/js/src/tests/non262/Iterator/prototype/lazy-methods-multiple-return-close-iterator-once.js new file mode 100644 index 0000000000..764215f747 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/lazy-methods-multiple-return-close-iterator-once.js @@ -0,0 +1,59 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +// +// +/*--- +esid: pending +description: Calling `.return()` on a lazy %Iterator.prototype% method multiple times closes the source iterator once. +info: > + Iterator Helpers proposal 2.1.5 +features: [iterator-helpers] +---*/ + +class TestIterator extends Iterator { + next() { + return {done: false, value: 1}; + } + + closeCount = 0; + return(value) { + this.closeCount++; + return {done: true, value}; + } +} + +const methods = [ + iter => iter.map(x => x), + iter => iter.filter(x => x), + iter => iter.take(1), + iter => iter.drop(0), + iter => iter.flatMap(x => [x]), +]; + +// Call `return` after stepping the iterator once: +for (const method of methods) { + const iter = new TestIterator(); + const iterHelper = method(iter); + iterHelper.next(); + + assertEq(iter.closeCount, 0); + iterHelper.return(); + assertEq(iter.closeCount, 1); + iterHelper.return(); + assertEq(iter.closeCount, 1); +} + +// Call `return` before stepping the iterator: +for (const method of methods) { + const iter = new TestIterator(); + const iterHelper = method(iter); + + assertEq(iter.closeCount, 0); + iterHelper.return(); + assertEq(iter.closeCount, 1); + iterHelper.return(); + assertEq(iter.closeCount, 1); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/lazy-methods-pass-through-lastValue.js b/js/src/tests/non262/Iterator/prototype/lazy-methods-pass-through-lastValue.js new file mode 100644 index 0000000000..173d7bb672 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/lazy-methods-pass-through-lastValue.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +class TestIterator extends Iterator { + next(value = "next value") { + assertEq(arguments.length, 0); + return {done: false, value}; + } +} + +const methods = [ + iter => iter.map(x => x), + iter => iter.filter(x => true), + iter => iter.take(2), + iter => iter.drop(0), +]; + +for (const method of methods) { + const iterator = new TestIterator(); + const iteratorHelper = method(iterator); + iteratorHelper.next(); + let result = iteratorHelper.next('last value'); + assertEq(result.done, false); + assertEq(result.value, 'next value'); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); + diff --git a/js/src/tests/non262/Iterator/prototype/lazy-methods-pass-value-through-chain.js b/js/src/tests/non262/Iterator/prototype/lazy-methods-pass-value-through-chain.js new file mode 100644 index 0000000000..491acea7be --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/lazy-methods-pass-value-through-chain.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +class TestIterator extends Iterator { + next(value = "next value") { + assertEq(arguments.length, 0); + return {done: false, value}; + } +} + +const methods = [ + iter => iter.map(x => x), + iter => iter.filter(x => true), + iter => iter.take(2), + iter => iter.drop(0), +]; + +for (const outerMethod of methods) { + for (const innerMethod of methods) { + const iterator = new TestIterator(); + const iteratorChain = outerMethod(innerMethod(iterator)); + iteratorChain.next(); + let result = iteratorChain.next('last value'); + assertEq(result.done, false); + assertEq(result.value, 'next value'); + } +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/lazy-methods-proxy-accesses.js b/js/src/tests/non262/Iterator/prototype/lazy-methods-proxy-accesses.js new file mode 100644 index 0000000000..31d2b903dd --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/lazy-methods-proxy-accesses.js @@ -0,0 +1,69 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) +// + +/*--- +esid: pending +description: Lazy %Iterator.prototype% methods access specified properties only. +info: > +features: [iterator-helpers] +---*/ + +class TestIterator extends Iterator { + value = 0; + next() { + if (this.value < 2) + return { done: false, value: this.value++ }; + return { done: true, value: undefined }; + } +} + +const handlerProxy = log => new Proxy({}, { + get: (target, key, receiver) => (...args) => { + const target = args[0]; + const item = Reflect[key](...args); + + log.push(`${key}: ${args.filter(x => typeof x != 'object').map(x => x.toString())}`); + + return item; + }, +}); + +const methods = [ + [iter => iter.map(x => x), 'map'], + [iter => iter.filter(x => true), 'filter'], + [iter => iter.take(4), 'take'], + [iter => iter.drop(0), 'drop'], + [iter => iter.flatMap(x => [x]), 'flatMap'], +]; + +for (const method of methods) { + const log = []; + const iteratorProxy = new Proxy(new TestIterator(), handlerProxy(log)); + const iteratorHelper = method[0](iteratorProxy); + const methodName = method[1]; + + iteratorHelper.next(); + iteratorHelper.next(); + iteratorHelper.next(); + assertEq(iteratorHelper.next().done, true); + + assertEq( + log.join('\n'), + `get: ${methodName} +get: next +get: value +get: value +getOwnPropertyDescriptor: value +defineProperty: value +set: value,1 +get: value +get: value +getOwnPropertyDescriptor: value +defineProperty: value +set: value,2 +get: value` + ) +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/lazy-methods-reentry-not-close-iterator.js b/js/src/tests/non262/Iterator/prototype/lazy-methods-reentry-not-close-iterator.js new file mode 100644 index 0000000000..da1e4c8c29 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/lazy-methods-reentry-not-close-iterator.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +const methods = [ + [iter => iter.map, x => x], + [iter => iter.filter, x => true], + [iter => iter.flatMap, x => [x]], +]; + +for (const method of methods) { + const iter = [1, 2, 3].values(); + const iterMethod = method[0](iter); + let iterHelper; + let reentered = false; + iterHelper = iterMethod.call(iter, x => { + if (x == 2) { + // Reenter the currently running generator. + reentered = true; + assertThrowsInstanceOf(() => iterHelper.next(), TypeError); + } + return method[1](x); + }); + + let result = iterHelper.next(); + assertEq(result.value, 1); + assertEq(result.done, false); + + assertEq(reentered, false); + result = iterHelper.next(); + assertEq(reentered, true); + assertEq(result.value, 2); + assertEq(result.done, false); + + result = iterHelper.next(); + assertEq(result.value, 3); + assertEq(result.done, false); + + result = iterHelper.next(); + assertEq(result.value, undefined); + assertEq(result.done, true); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/lazy-methods-return-closes-iterator.js b/js/src/tests/non262/Iterator/prototype/lazy-methods-return-closes-iterator.js new file mode 100644 index 0000000000..040bf45b47 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/lazy-methods-return-closes-iterator.js @@ -0,0 +1,57 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +// +// +/*--- +esid: pending +description: Calling `.return()` on a lazy %Iterator.prototype% method closes the source iterator. +info: > + Iterator Helpers proposal 2.1.5 +features: [iterator-helpers] +---*/ + +class TestIterator extends Iterator { + next() { + return {done: false, value: 1}; + } + + closed = false; + return(value) { + this.closed = true; + return {done: true, value}; + } +} + +const methods = [ + iter => iter.map(x => x), + iter => iter.filter(x => x), + iter => iter.take(1), + iter => iter.drop(0), + iter => iter.flatMap(x => [x]), +]; + +for (const method of methods) { + const iter = new TestIterator(); + const iterHelper = method(iter); + iterHelper.next(); + + assertEq(iter.closed, false); + const result = iterHelper.return("ignored"); + assertEq(iter.closed, true); + assertEq(result.done, true); + assertEq(result.value, undefined); +} + +for (const method of methods) { + const iter = new TestIterator(); + const iterHelper = method(iter); + + assertEq(iter.closed, false); + const result = iterHelper.return("ignored"); + assertEq(iter.closed, true); + assertEq(result.done, true); + assertEq(result.value, undefined); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/lazy-methods-return-new-iterator-result.js b/js/src/tests/non262/Iterator/prototype/lazy-methods-return-new-iterator-result.js new file mode 100644 index 0000000000..8f4708dd09 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/lazy-methods-return-new-iterator-result.js @@ -0,0 +1,38 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +// +// +/*--- +esid: pending +description: Lazy Iterator Helper methods return new iterator result objects. +info: > + Iterator Helpers proposal 2.1.5 +features: [iterator-helpers] +---*/ + +const iterResult = {done: false, value: 1, testProperty: 'test'}; +class TestIterator extends Iterator { + next() { + return iterResult; + } +} + +const methods = [ + iter => iter.map(x => x), + iter => iter.filter(x => true), + iter => iter.take(1), + iter => iter.drop(0), + iter => iter.flatMap(x => [x]), +]; + +// Call `return` before stepping the iterator: +for (const method of methods) { + const iter = new TestIterator(); + const iterHelper = method(iter); + const result = iterHelper.next(); + assertEq(result == iterResult, false); + assertEq(result.testProperty, undefined); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/lazy-methods-throw-eagerly-on-next-non-callable.js b/js/src/tests/non262/Iterator/prototype/lazy-methods-throw-eagerly-on-next-non-callable.js new file mode 100644 index 0000000000..35dd627acf --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/lazy-methods-throw-eagerly-on-next-non-callable.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +// +// +/*--- +esid: pending +description: Lazy %Iterator.prototype% methods don't throw when `next` is non-callable. +info: > + Iterator Helpers proposal 1.1.1 +features: [iterator-helpers] +---*/ + +const methods = [ + next => Iterator.prototype.map.bind({next}, x => x), + next => Iterator.prototype.filter.bind({next}, x => x), + next => Iterator.prototype.take.bind({next}, 1), + next => Iterator.prototype.drop.bind({next}, 0), + next => Iterator.prototype.flatMap.bind({next}, x => [x]), +]; + +for (const method of methods) { + method(0); + method(false); + method(undefined); + method(null); + method(''); + method(Symbol('')); + method({}); + method([]); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/lazy-methods-throw-eagerly-on-non-callable.js b/js/src/tests/non262/Iterator/prototype/lazy-methods-throw-eagerly-on-non-callable.js new file mode 100644 index 0000000000..7c31a21a38 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/lazy-methods-throw-eagerly-on-non-callable.js @@ -0,0 +1,38 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +// +// +/*--- +esid: pending +description: Lazy %Iterator.prototype% methods throw eagerly when passed non-callables. +info: > + Iterator Helpers proposal 2.1.5 +features: [iterator-helpers] +---*/ + +const methods = [ + (iter, fn) => iter.map(fn), + (iter, fn) => iter.filter(fn), + (iter, fn) => iter.flatMap(fn), +]; + +for (const method of methods) { + assertThrowsInstanceOf(() => method(Iterator.prototype, 0), TypeError); + assertThrowsInstanceOf(() => method(Iterator.prototype, false), TypeError); + assertThrowsInstanceOf(() => method(Iterator.prototype, undefined), TypeError); + assertThrowsInstanceOf(() => method(Iterator.prototype, null), TypeError); + assertThrowsInstanceOf(() => method(Iterator.prototype, ''), TypeError); + assertThrowsInstanceOf(() => method(Iterator.prototype, Symbol('')), TypeError); + assertThrowsInstanceOf(() => method(Iterator.prototype, {}), TypeError); + + assertThrowsInstanceOf(() => method([].values(), 0), TypeError); + assertThrowsInstanceOf(() => method([].values(), false), TypeError); + assertThrowsInstanceOf(() => method([].values(), undefined), TypeError); + assertThrowsInstanceOf(() => method([].values(), null), TypeError); + assertThrowsInstanceOf(() => method([].values(), ''), TypeError); + assertThrowsInstanceOf(() => method([].values(), Symbol('')), TypeError); + assertThrowsInstanceOf(() => method([].values(), {}), TypeError); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/lazy-methods-throw-eagerly-on-non-iterator.js b/js/src/tests/non262/Iterator/prototype/lazy-methods-throw-eagerly-on-non-iterator.js new file mode 100644 index 0000000000..5eafd0d9d7 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/lazy-methods-throw-eagerly-on-non-iterator.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +// +// +/*--- +esid: pending +description: Lazy %Iterator.prototype% methods don't throw when called with non-objects. +info: > + Iterator Helpers proposal 1.1.1 +features: [iterator-helpers] +---*/ + +const methods = [ + iter => Iterator.prototype.map.bind(iter, x => x), + iter => Iterator.prototype.filter.bind(iter, x => x), + iter => Iterator.prototype.take.bind(iter, 1), + iter => Iterator.prototype.drop.bind(iter, 0), + iter => Iterator.prototype.flatMap.bind(iter, x => [x]), +]; + +for (const method of methods) { + assertThrowsInstanceOf(method(undefined), TypeError); + assertThrowsInstanceOf(method(null), TypeError); + assertThrowsInstanceOf(method(0), TypeError); + assertThrowsInstanceOf(method(false), TypeError); + assertThrowsInstanceOf(method(''), TypeError); + assertThrowsInstanceOf(method(Symbol('')), TypeError); + + // No error here. + method({}); + method([]); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/lazy-methods-throw-next-done-throws.js b/js/src/tests/non262/Iterator/prototype/lazy-methods-throw-next-done-throws.js new file mode 100644 index 0000000000..7d6ad3cc98 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/lazy-methods-throw-next-done-throws.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +// +// +/*--- +esid: pending +description: Lazy %Iterator.prototype% methods throw if `next.done` throws. +info: > + Iterator Helpers proposal 2.1.5 +features: [iterator-helpers] +---*/ + +class TestError extends Error {} +class TestIterator extends Iterator { + next() { + return { + get done() { + throw new TestError(); + } + }; + } + + closed = false; + return() { + this.closed = true; + return {done: true}; + } +} + +const methods = [ + iter => iter.map(x => x), + iter => iter.filter(x => x), + iter => iter.take(1), + iter => iter.drop(0), + iter => iter.flatMap(x => [x]), +]; + +for (const method of methods) { + const iterator = new TestIterator(); + assertEq(iterator.closed, false); + assertThrowsInstanceOf(() => method(iterator).next(), TestError); + assertEq(iterator.closed, false); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/lazy-methods-throw-next-not-object.js b/js/src/tests/non262/Iterator/prototype/lazy-methods-throw-next-not-object.js new file mode 100644 index 0000000000..90e466f45d --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/lazy-methods-throw-next-not-object.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +// +// +/*--- +esid: pending +description: Lazy %Iterator.prototype% methods throw if `next` call returns a non-object. +info: > + Iterator Helpers proposal 2.1.5 +features: [iterator-helpers] +---*/ + +class TestIterator extends Iterator { + next(value) { + return value; + } + + closed = false; + return() { + this.closed = true; + return {done: true}; + } +} + +const methods = [ + iter => iter.map(x => x), + iter => iter.filter(x => x), + iter => iter.take(1), + iter => iter.drop(0), + iter => iter.flatMap(x => [x]), +]; + +for (const method of methods) { + for (const value of [undefined, null, 0, false, '', Symbol('')]) { + const iterator = new TestIterator(); + assertEq(iterator.closed, false); + assertThrowsInstanceOf(() => method(iterator).next(value), TypeError); + assertEq(iterator.closed, false); + } +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/lazy-methods-throw-on-reentry.js b/js/src/tests/non262/Iterator/prototype/lazy-methods-throw-on-reentry.js new file mode 100644 index 0000000000..1095842f55 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/lazy-methods-throw-on-reentry.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +const methods = [ + iter => iter.map, + iter => iter.filter, + iter => iter.flatMap, +]; + +for (const method of methods) { + const iter = [1].values(); + const iterMethod = method(iter); + let iterHelper; + iterHelper = iterMethod.call(iter, x => iterHelper.next()); + assertThrowsInstanceOf(() => iterHelper.next(), TypeError); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/map/call-next-on-iterator-while-iterating.js b/js/src/tests/non262/Iterator/prototype/map/call-next-on-iterator-while-iterating.js new file mode 100644 index 0000000000..a5a10120a0 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/map/call-next-on-iterator-while-iterating.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +/*--- +esid: pending +description: Call next on an iterator that is being iterated over. +info: +features: [iterator-helpers] +---*/ + +const iterator = [1, 2, 3].values() +const items = []; + +for (const item of iterator.map(x => x ** 2)) { + const nextItem = iterator.next(); + items.push(item, nextItem.value); +} + +assertEq(items[0], 1); +assertEq(items[1], 2); +assertEq(items[2], 9); +assertEq(items[3], undefined); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/map/clobber-symbol.js b/js/src/tests/non262/Iterator/prototype/map/clobber-symbol.js new file mode 100644 index 0000000000..8d5b2721e1 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/map/clobber-symbol.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +// +// + +/*--- +esid: pending +description: %Iterator.prototype%.map works even if the global Symbol has been clobbered.. +info: +features: [iterator-helpers, Symbol, Symbol.iterator] +---*/ + +Symbol = undefined; +assertThrowsInstanceOf(() => Symbol.iterator, TypeError); + +const iterator = [0].values(); +assertEq( + iterator.map(x => x + 1).next().value, 1, + '`%Iterator.prototype%.map` still works after Symbol has been clobbered' +); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/map/interleaved-map-calls.js b/js/src/tests/non262/Iterator/prototype/map/interleaved-map-calls.js new file mode 100644 index 0000000000..3253e06192 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/map/interleaved-map-calls.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) +// + +/*--- +esid: pending +description: Interleaved %Iterator.prototype%.map calls on the same iterator. +info: +features: [iterator-helpers] +---*/ + +const iterator = [1, 2, 3].values(); +const mapped1 = iterator.map(x => x); +const mapped2 = iterator.map(x => 0); + +assertEq(mapped1.next().value, 1); +assertEq(mapped2.next().value, 0); +assertEq(mapped1.next().value, 3); + +assertEq(mapped1.next().done, true); +assertEq(mapped2.next().done, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/map/length.js b/js/src/tests/non262/Iterator/prototype/map/length.js new file mode 100644 index 0000000000..d6bc1ca774 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/map/length.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) +// + +/*--- +esid: pending +description: %Iterator.prototype%.map length value and descriptor. +info: > + 17 ECMAScript Standard Built-in Objects +includes: [propertyHelper.js] +features: [Symbol.iterator] +---*/ + +assertEq(Iterator.prototype.map.length, 1); + +const propertyDescriptor = Reflect.getOwnPropertyDescriptor(Iterator.prototype.map, 'length'); +assertEq(propertyDescriptor.value, 1); +assertEq(propertyDescriptor.enumerable, false); +assertEq(propertyDescriptor.writable, false); +assertEq(propertyDescriptor.configurable, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/map/map.js b/js/src/tests/non262/Iterator/prototype/map/map.js new file mode 100644 index 0000000000..2cf5267be7 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/map/map.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +/*--- +esid: pending +description: %Iterator.prototype%.map value and descriptor. +info: > + 17 ECMAScript Standard Built-in Objects +features: [iterator-helpers] +---*/ + +const map = Reflect.getOwnPropertyDescriptor(Iterator.prototype, 'map'); + +assertEq( + Iterator.prototype.map, map.value, + 'The value of `%Iterator.prototype%.map` is the same as the value in the property descriptor.' +); + +assertEq( + typeof map.value, 'function', + '%Iterator.prototype%.map is a function.' +); + +assertEq(map.enumerable, false); +assertEq(map.writable, true); +assertEq(map.configurable, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/map/mapper-not-callable-throw.js b/js/src/tests/non262/Iterator/prototype/map/mapper-not-callable-throw.js new file mode 100644 index 0000000000..334e0fd8f9 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/map/mapper-not-callable-throw.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) +// + +/*--- +esid: pending +description: Eagerly throw TypeError when `mapper` is not callable. +info: +features: [iterator-helpers] +---*/ + +assertThrowsInstanceOf(() => Iterator.prototype.map(undefined), TypeError); +assertThrowsInstanceOf(() => [].values().map(undefined), TypeError); + +assertThrowsInstanceOf(() => Iterator.prototype.map(null), TypeError); +assertThrowsInstanceOf(() => [].values().map(null), TypeError); + +assertThrowsInstanceOf(() => Iterator.prototype.map(0), TypeError); +assertThrowsInstanceOf(() => [].values().map(0), TypeError); + +assertThrowsInstanceOf(() => Iterator.prototype.map(false), TypeError); +assertThrowsInstanceOf(() => [].values().map(false), TypeError); + +assertThrowsInstanceOf(() => Iterator.prototype.map({}), TypeError); +assertThrowsInstanceOf(() => [].values().map({}), TypeError); + +assertThrowsInstanceOf(() => Iterator.prototype.map(''), TypeError); +assertThrowsInstanceOf(() => [].values().map(''), TypeError); + +assertThrowsInstanceOf(() => Iterator.prototype.map(Symbol('')), TypeError); +assertThrowsInstanceOf(() => [].values().map(Symbol('')), TypeError); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/map/mutate-iterator-after-done.js b/js/src/tests/non262/Iterator/prototype/map/mutate-iterator-after-done.js new file mode 100644 index 0000000000..b38158d73a --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/map/mutate-iterator-after-done.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) +// + +/*--- +esid: pending +description: Mutate an iterator after it has been mapped and returned done. +info: +features: [iterator-helpers] +---*/ + +const array = [1, 2, 3]; +const iterator = [1, 2, 3].values().map(x => x * 2); + +assertEq(iterator.next().value, 2); +assertEq(iterator.next().value, 4); +assertEq(iterator.next().value, 6); +assertEq(iterator.next().done, true); + +array.push(4); +assertEq(iterator.next().done, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/map/mutate-iterator.js b/js/src/tests/non262/Iterator/prototype/map/mutate-iterator.js new file mode 100644 index 0000000000..b1cc52fae5 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/map/mutate-iterator.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) +// + +/*--- +esid: pending +description: Mutate an iterator after it has been mapped. +info: +features: [iterator-helpers] +---*/ + +const array = [1, 2, 3]; +const iterator = array.values().map(x => x * 2); +array.push(4); + +assertEq(iterator.next().value, 2); +assertEq(iterator.next().value, 4); +assertEq(iterator.next().value, 6); +assertEq(iterator.next().value, 8); +assertEq(iterator.next().done, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/map/name.js b/js/src/tests/non262/Iterator/prototype/map/name.js new file mode 100644 index 0000000000..3ba024d6e7 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/map/name.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) +/*--- +esid: pending +description: %Iterator.prototype%.map.name value and descriptor. +info: > + 17 ECMAScript Standard Built-in Objects +features: [iterator-helpers] +---*/ + +assertEq(Iterator.prototype.map.name, 'map'); + +const propertyDescriptor = Reflect.getOwnPropertyDescriptor(Iterator.prototype.map, 'name'); +assertEq(propertyDescriptor.value, 'map'); +assertEq(propertyDescriptor.enumerable, false); +assertEq(propertyDescriptor.writable, false); +assertEq(propertyDescriptor.configurable, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/map/output-at-generator-end.js b/js/src/tests/non262/Iterator/prototype/map/output-at-generator-end.js new file mode 100644 index 0000000000..69ef04a7b2 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/map/output-at-generator-end.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) +// + +/*--- +esid: pending +description: %Iterator.prototype%.map outputs correct value at end of iterator. +info: +features: [iterator-helpers] +---*/ + +const iterator = [0].values().map(x => x); + +const iterRecord = iterator.next(); +assertEq(iterRecord.done, false); +assertEq(iterRecord.value, 0); + +let endRecord = iterator.next(); +assertEq(endRecord.done, true); +assertEq(endRecord.value, undefined); + +endRecord = iterator.next(); +assertEq(endRecord.done, true); +assertEq(endRecord.value, undefined); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/map/pass-lastValue-to-next.js b/js/src/tests/non262/Iterator/prototype/map/pass-lastValue-to-next.js new file mode 100644 index 0000000000..99ae4face5 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/map/pass-lastValue-to-next.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) +// + +/*--- +esid: pending +description: %Iterator.prototype%.map passes lastValue to the `next` call. +info: > + Iterator Helpers Proposal 2.1.5.2 +features: [iterator-helpers] +---*/ + +const iteratorWhereNextTakesValue = Object.setPrototypeOf({ + next: function(value) { + assertEq(arguments.length, 0); + + if (this.value < 3) + return { done: false, value: this.value++ }; + return { done: true, value: undefined }; + }, + value: 0, +}, Iterator.prototype); + +const mappedIterator = iteratorWhereNextTakesValue.map(x => x); + +assertEq(mappedIterator.next(1).value, 0); + +assertEq(mappedIterator.next(2).value, 1); + +assertEq(mappedIterator.next(3).value, 2); + +assertEq(mappedIterator.next(4).done, true); + +assertEq(mappedIterator.next(5).done, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/map/proxy-abrupt-completion-in-iteratorValue.js b/js/src/tests/non262/Iterator/prototype/map/proxy-abrupt-completion-in-iteratorValue.js new file mode 100644 index 0000000000..f50bd0da10 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/map/proxy-abrupt-completion-in-iteratorValue.js @@ -0,0 +1,55 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) +// + +/*--- +esid: pending +description: %Iterator.prototype%.map does not call return when IteratorValue returns an abrupt completion. +info: > +features: [iterator-helpers] +---*/ + +const handlerProxy = log => new Proxy({}, { + get: (target, key, receiver) => (...args) => { + const target = args[0]; + const item = Reflect[key](...args); + + log.push(`${key}: ${args.filter(x => typeof x != 'object').map(x => x.toString())}`); + + switch (typeof item) { + case 'function': return item.bind(new Proxy(target, handlerProxy(log))); + case 'object': return new Proxy(item, handlerProxy(log)); + default: return item; + } + }, +}); + +const log = []; +const iterator = Object.setPrototypeOf({ + next: function() { + throw 'error'; + return { done: false, value: 0 }; + }, + return: function(value) { + log.push('close iterator'); + return { done: true, value }; + }, +}, Iterator.prototype); +const iteratorProxy = new Proxy(iterator, handlerProxy(log)); +const mappedProxy = iteratorProxy.map(x => x); + +try { + mappedProxy.next(); +} catch (exc) { + assertEq(exc, 'error'); +} + +console.log(log.join('\n')); + +assertEq( + log.join('\n'), +`get: map +get: next` +); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/map/proxy-abrupt-completion-in-yield.js b/js/src/tests/non262/Iterator/prototype/map/proxy-abrupt-completion-in-yield.js new file mode 100644 index 0000000000..9eb782e52a --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/map/proxy-abrupt-completion-in-yield.js @@ -0,0 +1,62 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) +// + +/*--- +esid: pending +description: %Iterator.prototype%.map calls return when yield throws. +info: > +features: [iterator-helpers] +---*/ + +class TestError extends Error {} + +class TestIterator extends Iterator { + constructor(log) { + super(); + this.log = log; + } + + next() { + return {done: false, value: 0}; + } + + return(value) { + log.push('close iterator'); + return {done: true, value}; + } +} + +const handlerProxy = log => new Proxy({}, { + get: (target, key, receiver) => (...args) => { + const target = args[0]; + const item = Reflect[key](...args); + + log.push(`${key}: ${args.filter(x => typeof x != 'object').map(x => x.toString())}`); + + switch (typeof item) { + case 'function': return item.bind(new Proxy(target, handlerProxy(log))); + case 'object': return new Proxy(item, handlerProxy(log)); + default: return item; + } + }, +}); + +const log = []; +const iterator = new TestIterator(log); +const iteratorProxy = new Proxy(iterator, handlerProxy(log)); +const mappedProxy = iteratorProxy.map(x => x); + +mappedProxy.next(); +mappedProxy.return(); +mappedProxy.next(); + +assertEq( + log.join('\n'), +`get: map +get: next +get: return +close iterator` +); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/map/proxy-abrupt-completion.js b/js/src/tests/non262/Iterator/prototype/map/proxy-abrupt-completion.js new file mode 100644 index 0000000000..ea0e10bdb4 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/map/proxy-abrupt-completion.js @@ -0,0 +1,54 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) +// + +/*--- +esid: pending +description: %Iterator.prototype%.map accesses specified properties only. +info: > +features: [iterator-helpers] +---*/ + +const handlerProxy = log => new Proxy({}, { + get: (target, key, receiver) => (...args) => { + const target = args[0]; + const item = Reflect[key](...args); + + log.push(`${key}: ${args.filter(x => typeof x != 'object').map(x => x.toString())}`); + + switch (typeof item) { + case 'function': return item.bind(new Proxy(target, handlerProxy(log))); + case 'object': return new Proxy(item, handlerProxy(log)); + default: return item; + } + }, +}); + +const log = []; +const iterator = Object.setPrototypeOf({ + next: function() { + return { done: false, value: 0 }; + }, + return: function(value) { + log.push('close iterator'); + return { done: true, value }; + }, +}, Iterator.prototype); +const iteratorProxy = new Proxy(iterator, handlerProxy(log)); +const mappedProxy = iteratorProxy.map(x => { throw 'error'; }); + +try { + mappedProxy.next(); +} catch (exc) { + assertEq(exc, 'error'); +} + +assertEq( + log.join('\n'), +`get: map +get: next +get: return +close iterator` +); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/map/proxy-accesses.js b/js/src/tests/non262/Iterator/prototype/map/proxy-accesses.js new file mode 100644 index 0000000000..ba6dfd7ece --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/map/proxy-accesses.js @@ -0,0 +1,94 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) +// + +/*--- +esid: pending +description: %Iterator.prototype%.map accesses specified properties only. +info: > +features: [iterator-helpers] +---*/ + +const handlerProxy = log => new Proxy({}, { + get: (target, key, receiver) => (...args) => { + const target = args[0]; + const item = Reflect[key](...args); + + log.push(`${key}: ${args.filter(x => typeof x != 'object').map(x => x.toString())}`); + + switch (typeof item) { + case 'function': return item.bind(new Proxy(target, handlerProxy(log))); + case 'object': return new Proxy(item, handlerProxy(log)); + default: return item; + } + }, +}); + +const log = []; +const iterator = Object.setPrototypeOf({ + next: function() { + if (this.value < 3) + return { done: false, value: this.value++ }; + return { done: true, value: undefined }; + }, + value: 0, +}, Iterator.prototype); +const iteratorProxy = new Proxy(iterator, handlerProxy(log)); +const mappedProxy = iteratorProxy.map(x => x); + +for (const item of mappedProxy) { +} + +assertEq( + log.join('\n'), +`get: map +get: next +get: value +get: value +getOwnPropertyDescriptor: value +has: enumerable +get: enumerable +has: configurable +get: configurable +has: value +get: value +has: writable +get: writable +has: get +has: set +defineProperty: value +set: value,1 +get: value +get: value +getOwnPropertyDescriptor: value +has: enumerable +get: enumerable +has: configurable +get: configurable +has: value +get: value +has: writable +get: writable +has: get +has: set +defineProperty: value +set: value,2 +get: value +get: value +getOwnPropertyDescriptor: value +has: enumerable +get: enumerable +has: configurable +get: configurable +has: value +get: value +has: writable +get: writable +has: get +has: set +defineProperty: value +set: value,3 +get: value` +); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/map/reenter-map-generator-from-mapper.js b/js/src/tests/non262/Iterator/prototype/map/reenter-map-generator-from-mapper.js new file mode 100644 index 0000000000..b7a0d56d5c --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/map/reenter-map-generator-from-mapper.js @@ -0,0 +1,15 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +// Re-entering the map() generator from the called mapper fails. + +let iterator; +function mapper(x) { + let n = iterator.next(); + return x; +} +iterator = [0].values().map(mapper); + +assertThrowsInstanceOf(iterator.next, TypeError); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/map/this-not-iterator-throw.js b/js/src/tests/non262/Iterator/prototype/map/this-not-iterator-throw.js new file mode 100644 index 0000000000..ac250db383 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/map/this-not-iterator-throw.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) +// + +/*--- +esid: pending +description: Eagerly throw TypeError when `this` is not an iterator. +info: +features: [iterator-helpers] +---*/ + +const mapper = (x) => x; + +assertThrowsInstanceOf(() => Iterator.prototype.map.call(undefined, mapper), TypeError); +assertThrowsInstanceOf(() => Iterator.prototype.map.call(null, mapper), TypeError); +assertThrowsInstanceOf(() => Iterator.prototype.map.call(0, mapper), TypeError); +assertThrowsInstanceOf(() => Iterator.prototype.map.call(false, mapper), TypeError); +assertThrowsInstanceOf(() => Iterator.prototype.map.call('', mapper), TypeError); +assertThrowsInstanceOf(() => Iterator.prototype.map.call(new Symbol(''), mapper), TypeError); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/map/this-value-array-throws.js b/js/src/tests/non262/Iterator/prototype/map/this-value-array-throws.js new file mode 100644 index 0000000000..3a13fefc97 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/map/this-value-array-throws.js @@ -0,0 +1,14 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) +// + +/*--- +esid: pending +description: TypeError not thrown when `this` is an Array. +info: +features: [Symbol.iterator] +---*/ + +Iterator.prototype.map.call([], x => x); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/map/throw-when-iterator-returns-non-object.js b/js/src/tests/non262/Iterator/prototype/map/throw-when-iterator-returns-non-object.js new file mode 100644 index 0000000000..287507a2f6 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/map/throw-when-iterator-returns-non-object.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) +// + +/*--- +esid: pending +description: Throw TypeError if `next` call returns non-object. +info: +features: [iterator-helpers] +---*/ + +const iterator = returnValue => Object.setPrototypeOf({ + next: () => returnValue, +}, Iterator.prototype); +const mapper = x => x; + +assertThrowsInstanceOf(() => iterator(undefined).map(mapper).next(), TypeError); +assertThrowsInstanceOf(() => iterator(null).map(mapper).next(), TypeError); +assertThrowsInstanceOf(() => iterator(0).map(mapper).next(), TypeError); +assertThrowsInstanceOf(() => iterator(false).map(mapper).next(), TypeError); +assertThrowsInstanceOf(() => iterator('').map(mapper).next(), TypeError); +assertThrowsInstanceOf(() => iterator(Symbol()).map(mapper).next(), TypeError); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/map/values-pass-through-chained-maps-to-next.js b/js/src/tests/non262/Iterator/prototype/map/values-pass-through-chained-maps-to-next.js new file mode 100644 index 0000000000..1873017981 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/map/values-pass-through-chained-maps-to-next.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) +// + +/*--- +esid: pending +description: Multiple chained %Iterator.prototype%.map calls pass `lastValue` to the iterator's `next` call. +info: > + Iterator Helpers Proposal 2.1.5.2 +features: [iterator-helpers] +---*/ + +const iteratorWhereNextTakesValue = Object.setPrototypeOf({ + next: function(value) { + assertEq(arguments.length, 0); + + if (this.value < 3) + return { done: false, value: this.value++ }; + return { done: true, value: undefined }; + }, + value: 0, +}, Iterator.prototype); + +const mappedIterator = iteratorWhereNextTakesValue.map(x => 2 * x).map(x => 1 + x); + +assertEq(mappedIterator.next(1).value, 1); + +assertEq(mappedIterator.next(2).value, 3); + +assertEq(mappedIterator.next(3).value, 5); + +assertEq(mappedIterator.next(4).done, true); + +assertEq(mappedIterator.next(5).done, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/reduce/accumulator-set-to-initial-value.js b/js/src/tests/non262/Iterator/prototype/reduce/accumulator-set-to-initial-value.js new file mode 100644 index 0000000000..4395e1c7d4 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/reduce/accumulator-set-to-initial-value.js @@ -0,0 +1,9 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const reducer = (acc, value) => acc; +const iterator = [1, 2, 3].values(); + +assertEq(iterator.reduce(reducer, 0), 0); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/reduce/check-fn-after-getting-iterator.js b/js/src/tests/non262/Iterator/prototype/reduce/check-fn-after-getting-iterator.js new file mode 100644 index 0000000000..ebb28c4980 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/reduce/check-fn-after-getting-iterator.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +const log = []; +const handlerProxy = new Proxy({}, { + get: (target, key, receiver) => (...args) => { + log.push(`${key}: ${args[1]?.toString()}`); + return Reflect[key](...args); + }, +}); + +class TestIterator extends Iterator { + next() { + return {done: true}; + } +} + +const iter = new Proxy(new TestIterator(), handlerProxy); +assertThrowsInstanceOf(() => iter.reduce(1), TypeError); + +assertEqArray( + log, + ["get: reduce"] +); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/reduce/descriptor.js b/js/src/tests/non262/Iterator/prototype/reduce/descriptor.js new file mode 100644 index 0000000000..0fb0ff01b3 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/reduce/descriptor.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + Descriptor property of Iterator.prototype.reduce +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(Iterator.prototype, 'reduce'); +assertEq(typeof propDesc.value, 'function'); +assertEq(propDesc.writable, true); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/reduce/empty-iterator-without-initial-value-throws.js b/js/src/tests/non262/Iterator/prototype/reduce/empty-iterator-without-initial-value-throws.js new file mode 100644 index 0000000000..d8e0a595cf --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/reduce/empty-iterator-without-initial-value-throws.js @@ -0,0 +1,7 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const iter = [].values(); +assertThrowsInstanceOf(() => iter.reduce((x, y) => x + y), TypeError); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/reduce/error-from-correct-realm.js b/js/src/tests/non262/Iterator/prototype/reduce/error-from-correct-realm.js new file mode 100644 index 0000000000..96634ba62b --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/reduce/error-from-correct-realm.js @@ -0,0 +1,16 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const otherGlobal = newGlobal({newCompartment: true}); +assertEq(TypeError !== otherGlobal.TypeError, true); + +const iter = [].values(); + +assertThrowsInstanceOf(() => iter.reduce(), TypeError); +assertThrowsInstanceOf( + otherGlobal.Iterator.prototype.reduce.bind(iter), + otherGlobal.TypeError, + 'TypeError comes from the realm of the method.', +); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/reduce/iterator-empty-return-initial-value.js b/js/src/tests/non262/Iterator/prototype/reduce/iterator-empty-return-initial-value.js new file mode 100644 index 0000000000..30c15a48fe --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/reduce/iterator-empty-return-initial-value.js @@ -0,0 +1,9 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const reducer = (x, y) => 0; +const iterator = [].values(); + +assertEq(iterator.reduce(reducer, 1), 1); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/reduce/iterator-next-return-non-object-throws.js b/js/src/tests/non262/Iterator/prototype/reduce/iterator-next-return-non-object-throws.js new file mode 100644 index 0000000000..d77789f04a --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/reduce/iterator-next-return-non-object-throws.js @@ -0,0 +1,30 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +class TestIterator extends Iterator { + constructor(value) { + super(); + this.value = value; + } + + next() { + return this.value; + } +} + +const sum = (x, y) => x + y; + +let iter = new TestIterator(undefined); +assertThrowsInstanceOf(() => iter.reduce(sum), TypeError); +iter = new TestIterator(null); +assertThrowsInstanceOf(() => iter.reduce(sum), TypeError); +iter = new TestIterator(0); +assertThrowsInstanceOf(() => iter.reduce(sum), TypeError); +iter = new TestIterator(false); +assertThrowsInstanceOf(() => iter.reduce(sum), TypeError); +iter = new TestIterator(''); +assertThrowsInstanceOf(() => iter.reduce(sum), TypeError); +iter = new TestIterator(Symbol('')); +assertThrowsInstanceOf(() => iter.reduce(sum), TypeError); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/reduce/left-associative.js b/js/src/tests/non262/Iterator/prototype/reduce/left-associative.js new file mode 100644 index 0000000000..a6208504b6 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/reduce/left-associative.js @@ -0,0 +1,7 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +assertEq([1, 2, 3].values().reduce((x, y) => `(${x}+${y})`, 0), '(((0+1)+2)+3)'); +assertEq([1, 2, 3].values().reduce((x, y) => `(${x}+${y})`), '((1+2)+3)'); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/reduce/length.js b/js/src/tests/non262/Iterator/prototype/reduce/length.js new file mode 100644 index 0000000000..0780e684a8 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/reduce/length.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + The `length` property of Iterator.prototype.reduce. +info: | + ES7 section 17: Unless otherwise specified, the length property of a built-in + Function object has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(Iterator.prototype.reduce, 'length'); +assertEq(propDesc.value, 1); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/reduce/name.js b/js/src/tests/non262/Iterator/prototype/reduce/name.js new file mode 100644 index 0000000000..1269bb4b52 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/reduce/name.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + `name` property of Iterator.prototype.reduce. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(Iterator.prototype.reduce, 'name'); +assertEq(propDesc.value, 'reduce'); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/reduce/next-throws-iterator-not-closed.js b/js/src/tests/non262/Iterator/prototype/reduce/next-throws-iterator-not-closed.js new file mode 100644 index 0000000000..0fbeb995f1 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/reduce/next-throws-iterator-not-closed.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +class TestIterator extends Iterator { + next() { + throw new Error(); + } + + closed = false; + return() { + this.closed = true; + } +} + +const sum = (x, y) => x + y; +const iter = new TestIterator(); + +assertEq(iter.closed, false); +assertThrowsInstanceOf(() => iter.reduce(sum), Error); +assertEq(iter.closed, false); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/reduce/no-initial-value-set-accumulator-to-first-value.js b/js/src/tests/non262/Iterator/prototype/reduce/no-initial-value-set-accumulator-to-first-value.js new file mode 100644 index 0000000000..a2b0008e6a --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/reduce/no-initial-value-set-accumulator-to-first-value.js @@ -0,0 +1,9 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const reducer = (acc, value) => acc; +const iterator = [1, 2, 3].values(); + +assertEq(iterator.reduce(reducer), 1); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/reduce/proxy.js b/js/src/tests/non262/Iterator/prototype/reduce/proxy.js new file mode 100644 index 0000000000..34569cf044 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/reduce/proxy.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +// +// This test checks that %Iterator.prototype%.reduce only gets the `next` method off of the +// iterator once, and never accesses the @@iterator property. +const log = []; +const handlerProxy = new Proxy({}, { + get: (target, key, receiver) => (...args) => { + log.push(`${key}: ${args[1]?.toString()}`); + return Reflect[key](...args); + }, +}); + +class Counter extends Iterator { + value = 0; + next() { + const value = this.value; + if (value < 2) { + this.value = value + 1; + return {done: false, value}; + } + return {done: true}; + } +} + +const iter = new Proxy(new Counter(), handlerProxy); +iter.reduce((x, y) => x + y); + +assertEq( + log.join('\n'), + `get: reduce +get: next +get: value +set: value +getOwnPropertyDescriptor: value +defineProperty: value +get: value +set: value +getOwnPropertyDescriptor: value +defineProperty: value +get: value` +); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/reduce/reduce.js b/js/src/tests/non262/Iterator/prototype/reduce/reduce.js new file mode 100644 index 0000000000..d824da211d --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/reduce/reduce.js @@ -0,0 +1,9 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const reducer = (acc, value) => acc + value; +const iterator = [1, 2, 3].values(); + +assertEq(iterator.reduce(reducer, 0), 6); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/reduce/reducer-not-callable-throws.js b/js/src/tests/non262/Iterator/prototype/reduce/reducer-not-callable-throws.js new file mode 100644 index 0000000000..c33e5e4f9c --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/reduce/reducer-not-callable-throws.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +class TestIterator extends Iterator { + next() { + return { done: false, value: 0 }; + } +} + +const iter = new TestIterator(); +assertThrowsInstanceOf(() => iter.reduce(), TypeError); +assertThrowsInstanceOf(() => iter.reduce(undefined), TypeError); +assertThrowsInstanceOf(() => iter.reduce(null), TypeError); +assertThrowsInstanceOf(() => iter.reduce(0), TypeError); +assertThrowsInstanceOf(() => iter.reduce(false), TypeError); +assertThrowsInstanceOf(() => iter.reduce(''), TypeError); +assertThrowsInstanceOf(() => iter.reduce(Symbol('')), TypeError); +assertThrowsInstanceOf(() => iter.reduce({}), TypeError); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/reduce/reducer-throws-iterator-closed.js b/js/src/tests/non262/Iterator/prototype/reduce/reducer-throws-iterator-closed.js new file mode 100644 index 0000000000..592fa80d17 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/reduce/reducer-throws-iterator-closed.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +class TestIterator extends Iterator { + next() { + return { done: this.closed, value: undefined }; + } + + closed = false; + return() { + this.closed = true; + } +} + +const reducer = (x, y) => { throw new Error(); }; +const iter = new TestIterator(); + +assertEq(iter.closed, false); +assertThrowsInstanceOf(() => iter.reduce(reducer), Error); +assertEq(iter.closed, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/reduce/this-not-iterator-throws.js b/js/src/tests/non262/Iterator/prototype/reduce/this-not-iterator-throws.js new file mode 100644 index 0000000000..d4804c51e2 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/reduce/this-not-iterator-throws.js @@ -0,0 +1,9 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const sum = (x, y) => x + y; +assertThrowsInstanceOf(Iterator.prototype.reduce.bind(undefined, sum), TypeError); +assertThrowsInstanceOf(Iterator.prototype.reduce.bind({}, sum), TypeError); +assertThrowsInstanceOf(Iterator.prototype.reduce.bind({next: 0}, sum), TypeError); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/reduce/value-throws-iterator-not-closed.js b/js/src/tests/non262/Iterator/prototype/reduce/value-throws-iterator-not-closed.js new file mode 100644 index 0000000000..7b43eedcc6 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/reduce/value-throws-iterator-not-closed.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +class TestError extends Error {} +class TestIterator extends Iterator { + next() { + return new Proxy({done: false}, {get: (target, key, receiver) => { + if (key === 'value') + throw new TestError(); + return 0; + }}); + } + + closed = false; + return() { + closed = true; + } +} + +const iterator = new TestIterator(); +assertEq(iterator.closed, false, 'iterator starts unclosed'); +assertThrowsInstanceOf(() => iterator.reduce((x, y) => x + y, 0), TestError); +assertEq(iterator.closed, false, 'iterator remains unclosed'); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/some/check-fn-after-getting-iterator.js b/js/src/tests/non262/Iterator/prototype/some/check-fn-after-getting-iterator.js new file mode 100644 index 0000000000..bfadc6810e --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/some/check-fn-after-getting-iterator.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +const log = []; +const handlerProxy = new Proxy({}, { + get: (target, key, receiver) => (...args) => { + log.push(`${key}: ${args[1]?.toString()}`); + return Reflect[key](...args); + }, +}); + +class TestIterator extends Iterator { + next() { + return {done: true}; + } +} + +const iter = new Proxy(new TestIterator(), handlerProxy); +assertThrowsInstanceOf(() => iter.some(1), TypeError); + +assertEqArray( + log, + ["get: some"] +); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/some/coerce-result-to-boolean.js b/js/src/tests/non262/Iterator/prototype/some/coerce-result-to-boolean.js new file mode 100644 index 0000000000..5bebdb06ea --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/some/coerce-result-to-boolean.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const fn = (value) => value; +assertEq([true].values().some(fn), true); +assertEq([1].values().some(fn), true); +assertEq([[]].values().some(fn), true); +assertEq([{}].values().some(fn), true); +assertEq(['test'].values().some(fn), true); + +assertEq([false].values().some(fn), false); +assertEq([0].values().some(fn), false); +assertEq([''].values().some(fn), false); +assertEq([null].values().some(fn), false); +assertEq([undefined].values().some(fn), false); +assertEq([NaN].values().some(fn), false); +assertEq([-0].values().some(fn), false); +assertEq([0n].values().some(fn), false); + +const htmlDDA = createIsHTMLDDA(); +assertEq([htmlDDA].values().some(fn), false); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/some/descriptor.js b/js/src/tests/non262/Iterator/prototype/some/descriptor.js new file mode 100644 index 0000000000..dfafc4aa5f --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/some/descriptor.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + Descriptor property of Iterator.prototype.some +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(Iterator.prototype, 'some'); +assertEq(typeof propDesc.value, 'function'); +assertEq(propDesc.writable, true); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/some/error-from-correct-realm.js b/js/src/tests/non262/Iterator/prototype/some/error-from-correct-realm.js new file mode 100644 index 0000000000..ba68c6e7c1 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/some/error-from-correct-realm.js @@ -0,0 +1,16 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const otherGlobal = newGlobal({newCompartment: true}); +assertEq(TypeError !== otherGlobal.TypeError, true); + +const iter = [].values(); + +assertThrowsInstanceOf(() => iter.some(), TypeError); +assertThrowsInstanceOf( + otherGlobal.Iterator.prototype.some.bind(iter), + otherGlobal.TypeError, + 'TypeError comes from the realm of the method.', +); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/some/fn-not-callable-throws.js b/js/src/tests/non262/Iterator/prototype/some/fn-not-callable-throws.js new file mode 100644 index 0000000000..52be15391f --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/some/fn-not-callable-throws.js @@ -0,0 +1,15 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const iter = [].values(); + +assertThrowsInstanceOf(() => iter.some(), TypeError); +assertThrowsInstanceOf(() => iter.some(undefined), TypeError); +assertThrowsInstanceOf(() => iter.some(null), TypeError); +assertThrowsInstanceOf(() => iter.some(0), TypeError); +assertThrowsInstanceOf(() => iter.some(false), TypeError); +assertThrowsInstanceOf(() => iter.some(''), TypeError); +assertThrowsInstanceOf(() => iter.some(Symbol('')), TypeError); +assertThrowsInstanceOf(() => iter.some({}), TypeError); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/some/fn-throws-close-iterator.js b/js/src/tests/non262/Iterator/prototype/some/fn-throws-close-iterator.js new file mode 100644 index 0000000000..bbe751e175 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/some/fn-throws-close-iterator.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +class TestIterator extends Iterator { + next() { + return { done: this.closed }; + } + + closed = false; + return() { + this.closed = true; + } +} + +const fn = () => { throw new Error(); }; +const iter = new TestIterator(); + +assertEq(iter.closed, false); +assertThrowsInstanceOf(() => iter.some(fn), Error); +assertEq(iter.closed, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/some/length.js b/js/src/tests/non262/Iterator/prototype/some/length.js new file mode 100644 index 0000000000..c9d1f986f6 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/some/length.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + The `length` property of Iterator.prototype.some. +info: | + ES7 section 17: Unless otherwise specified, the length property of a built-in + Function object has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(Iterator.prototype.some, 'length'); +assertEq(propDesc.value, 1); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/some/name.js b/js/src/tests/non262/Iterator/prototype/some/name.js new file mode 100644 index 0000000000..679e75460c --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/some/name.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + `name` property of Iterator.prototype.some. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(Iterator.prototype.some, 'name'); +assertEq(propDesc.value, 'some'); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/some/next-throws-iterator-not-closed.js b/js/src/tests/non262/Iterator/prototype/some/next-throws-iterator-not-closed.js new file mode 100644 index 0000000000..4bdf372908 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/some/next-throws-iterator-not-closed.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +class TestIterator extends Iterator { + next() { + throw new Error(); + } + + closed = false; + return() { + this.closed = true; + } +} + +const fn = () => {}; +const iter = new TestIterator(); + +assertEq(iter.closed, false); +assertThrowsInstanceOf(() => iter.some(fn), Error); +assertEq(iter.closed, false); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/some/proxy.js b/js/src/tests/non262/Iterator/prototype/some/proxy.js new file mode 100644 index 0000000000..a444a2d5cb --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/some/proxy.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +// +// This test checks that %Iterator.prototype%.some only gets the `next` method off of the +// iterator once, and never accesses the @@iterator property. +const log = []; +const handlerProxy = new Proxy({}, { + get: (target, key, receiver) => (...args) => { + log.push(`${key}: ${args[1]?.toString()}`); + return Reflect[key](...args); + }, +}); + +class Counter extends Iterator { + value = 0; + next() { + const value = this.value; + if (value < 2) { + this.value = value + 1; + return {done: false, value}; + } + return {done: true}; + } +} + +const iter = new Proxy(new Counter(), handlerProxy); +assertEq(iter.some(x => x % 2 == 1), true); + +assertEq( + log.join('\n'), + `get: some +get: next +get: value +set: value +getOwnPropertyDescriptor: value +defineProperty: value +get: value +set: value +getOwnPropertyDescriptor: value +defineProperty: value +get: return` +); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/some/return-false-if-none-match.js b/js/src/tests/non262/Iterator/prototype/some/return-false-if-none-match.js new file mode 100644 index 0000000000..00fab94245 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/some/return-false-if-none-match.js @@ -0,0 +1,11 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const iter = [1, 3, 5].values(); +const fn = (value) => value % 2 == 0; + +assertEq(iter.some(fn), false); + +assertEq([].values().some(x => x), false); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/some/short-circuit-on-true.js b/js/src/tests/non262/Iterator/prototype/some/short-circuit-on-true.js new file mode 100644 index 0000000000..4f0d67bf09 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/some/short-circuit-on-true.js @@ -0,0 +1,14 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const iter = [1, 2, 3].values(); +const log = []; +const fn = (value) => { + log.push(value.toString()); + return value % 2 == 0; +}; + +assertEq(iter.some(fn), true); +assertEq(log.join(','), '1,2'); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/some/this-not-iterator-throws.js b/js/src/tests/non262/Iterator/prototype/some/this-not-iterator-throws.js new file mode 100644 index 0000000000..0659ec037e --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/some/this-not-iterator-throws.js @@ -0,0 +1,9 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const fn = x => x; +assertThrowsInstanceOf(Iterator.prototype.some.bind(undefined, fn), TypeError); +assertThrowsInstanceOf(Iterator.prototype.some.bind({}, fn), TypeError); +assertThrowsInstanceOf(Iterator.prototype.some.bind({next: 0}, fn), TypeError); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/some/value-throws-iterator-not-closed.js b/js/src/tests/non262/Iterator/prototype/some/value-throws-iterator-not-closed.js new file mode 100644 index 0000000000..87bf5df033 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/some/value-throws-iterator-not-closed.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +class TestError extends Error {} +class TestIterator extends Iterator { + next() { + return new Proxy({done: false}, {get: (target, key, receiver) => { + if (key === 'value') + throw new TestError(); + return 0; + }}); + } + + closed = false; + return() { + closed = true; + } +} + +const iterator = new TestIterator(); +assertEq(iterator.closed, false, 'iterator starts unclosed'); +assertThrowsInstanceOf(() => iterator.some(x => x), TestError); +assertEq(iterator.closed, false, 'iterator remains unclosed'); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/take-drop-throw-eagerly-on-negative.js b/js/src/tests/non262/Iterator/prototype/take-drop-throw-eagerly-on-negative.js new file mode 100644 index 0000000000..8eef93ab09 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/take-drop-throw-eagerly-on-negative.js @@ -0,0 +1,30 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +// +// +/*--- +esid: pending +description: `take` and `drop` throw eagerly when passed negative numbers, after rounding towards 0. +info: > + Iterator Helpers proposal 2.1.5.4 and 2.1.5.5 +features: [iterator-helpers] +---*/ + +const iter = [].values(); +const methods = [ + value => iter.take(value), + value => iter.drop(value), +]; + +for (const method of methods) { + assertThrowsInstanceOf(() => method(-1), RangeError); + assertThrowsInstanceOf(() => method(-Infinity), RangeError); + assertThrowsInstanceOf(() => method(NaN), RangeError); + assertThrowsInstanceOf(() => method(-NaN), RangeError); + + method(-0); + method(-0.9); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/take-drop-throw-eagerly-on-non-integer.js b/js/src/tests/non262/Iterator/prototype/take-drop-throw-eagerly-on-non-integer.js new file mode 100644 index 0000000000..3e1333ab37 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/take-drop-throw-eagerly-on-non-integer.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +// +// +/*--- +esid: pending +description: `take` and `drop` throw eagerly when passed values that can't be converted to numbers. +info: > + Iterator Helpers proposal 2.1.5.4 and 2.1.5.5 +features: [iterator-helpers] +---*/ + +const iter = [].values(); +const methods = [ + value => iter.take(value), + value => iter.drop(value), +]; + +const objectWithToPrimitive = { + [Symbol.toPrimitive]() { + return {}; + } +}; + +for (const method of methods) { + assertThrowsInstanceOf(() => method(0n), TypeError); + assertThrowsInstanceOf(() => method(Symbol('')), TypeError); + assertThrowsInstanceOf(() => method(objectWithToPrimitive), TypeError); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/take/close-iterator-when-none-remaining.js b/js/src/tests/non262/Iterator/prototype/take/close-iterator-when-none-remaining.js new file mode 100644 index 0000000000..1c78db378b --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/take/close-iterator-when-none-remaining.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +// +// +/*--- +esid: pending +description: %Iterator.prototype%.take closes the iterator when remaining is 0. +info: > + Iterator Helpers proposal 2.1.5.4 +features: [iterator-helpers] +---*/ + +class TestIterator extends Iterator { + next() { + return {done: false, value: 1}; + } + + closed = false; + return() { + this.closed = true; + return {done: true}; + } +} + +const iter = new TestIterator(); +const iterTake = iter.take(1); + +let result = iterTake.next(); +assertEq(result.done, false); +assertEq(result.value, 1); +assertEq(iter.closed, false); + +result = iterTake.next(); +assertEq(result.done, true); +assertEq(result.value, undefined); +assertEq(iter.closed, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); + diff --git a/js/src/tests/non262/Iterator/prototype/take/length.js b/js/src/tests/non262/Iterator/prototype/take/length.js new file mode 100644 index 0000000000..4e5efa6cea --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/take/length.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) +// + +/*--- +esid: pending +description: %Iterator.prototype%.take length value and descriptor. +info: > + 17 ECMAScript Standard Built-in Objects +includes: [propertyHelper.js] +features: [Symbol.iterator] +---*/ + +assertEq(Iterator.prototype.take.length, 1); + +const propertyDescriptor = Reflect.getOwnPropertyDescriptor(Iterator.prototype.take, 'length'); +assertEq(propertyDescriptor.value, 1); +assertEq(propertyDescriptor.enumerable, false); +assertEq(propertyDescriptor.writable, false); +assertEq(propertyDescriptor.configurable, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/take/name.js b/js/src/tests/non262/Iterator/prototype/take/name.js new file mode 100644 index 0000000000..87f75b63dd --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/take/name.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) +/*--- +esid: pending +description: %Iterator.prototype%.take.name value and descriptor. +info: > + 17 ECMAScript Standard Built-in Objects +features: [iterator-helpers] +---*/ + +assertEq(Iterator.prototype.take.name, 'take'); + +const propertyDescriptor = Reflect.getOwnPropertyDescriptor(Iterator.prototype.take, 'name'); +assertEq(propertyDescriptor.value, 'take'); +assertEq(propertyDescriptor.enumerable, false); +assertEq(propertyDescriptor.writable, false); +assertEq(propertyDescriptor.configurable, true); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/take/take-more-than-available.js b/js/src/tests/non262/Iterator/prototype/take/take-more-than-available.js new file mode 100644 index 0000000000..b9d07b6122 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/take/take-more-than-available.js @@ -0,0 +1,52 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) + +// +// +/*--- +esid: pending +description: %Iterator.prototype%.take returns if the iterator is done. +info: > + Iterator Helpers proposal 2.1.5.4 + 2. Repeat, + ... + c. Let next be ? IteratorStep(iterated, lastValue). + d. If next is false, return undefined. +features: [iterator-helpers] +---*/ + +let iter = [1, 2].values().take(3); +for (const expected of [1, 2]) { + const result = iter.next(); + assertEq(result.value, expected); + assertEq(result.done, false); +} +let result = iter.next(); +assertEq(result.value, undefined); +assertEq(result.done, true); + +class TestIterator extends Iterator { + counter = 0; + next() { + return {done: ++this.counter >= 2, value: undefined}; + } + + closed = false; + return(value) { + this.closed = true; + return {done: true, value}; + } +} + +iter = new TestIterator(); +let taken = iter.take(10); +for (const value of taken) { + assertEq(value, undefined); +} +result = taken.next(); +assertEq(result.value, undefined); +assertEq(result.done, true); +assertEq(iter.counter, 2); +assertEq(iter.closed, false); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/take/take.js b/js/src/tests/non262/Iterator/prototype/take/take.js new file mode 100644 index 0000000000..cff93bf278 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/take/take.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('AsyncIterator')) + +/*--- +esid: pending +description: Smoketest of %Iterator.prototype%.take. +info: > + Iterator Helpers proposal 2.1.5.4 +features: [iterator-helpers] +---*/ + +let iter = [1, 2, 3].values().take(2); + +for (const v of [1, 2]) { + let result = iter.next(); + assertEq(result.done, false); + assertEq(result.value, v); +} + +assertEq(iter.next().done, true); + +// `take`, when called without arguments, throws a RangeError, +assertThrowsInstanceOf(() => ['test'].values().take(), RangeError); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/toArray/create-in-current-realm.js b/js/src/tests/non262/Iterator/prototype/toArray/create-in-current-realm.js new file mode 100644 index 0000000000..850729e5e3 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/toArray/create-in-current-realm.js @@ -0,0 +1,14 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const otherGlobal = newGlobal({newCompartment: true}); + +let array = [1, 2, 3].values().toArray(); +assertEq(array instanceof Array, true); +assertEq(array instanceof otherGlobal.Array, false); + +array = otherGlobal.Iterator.prototype.toArray.call([1, 2, 3].values()); +assertEq(array instanceof Array, false); +assertEq(array instanceof otherGlobal.Array, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/toArray/descriptor.js b/js/src/tests/non262/Iterator/prototype/toArray/descriptor.js new file mode 100644 index 0000000000..8daa56fd4a --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/toArray/descriptor.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + Descriptor property of Iterator.prototype.toArray +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(Iterator.prototype, 'toArray'); +assertEq(typeof propDesc.value, 'function'); +assertEq(propDesc.writable, true); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/toArray/iterator-empty.js b/js/src/tests/non262/Iterator/prototype/toArray/iterator-empty.js new file mode 100644 index 0000000000..97c14f0d06 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/toArray/iterator-empty.js @@ -0,0 +1,10 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const iter = [].values(); +const array = iter.toArray(); + +assertEq(Array.isArray(array), true); +assertEq(array.length, 0); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/toArray/length.js b/js/src/tests/non262/Iterator/prototype/toArray/length.js new file mode 100644 index 0000000000..493a225ce7 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/toArray/length.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + The `length` property of Iterator.prototype.toArray. +info: | + ES7 section 17: Unless otherwise specified, the length property of a built-in + Function object has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(Iterator.prototype.toArray, 'length'); +assertEq(propDesc.value, 0); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/toArray/name.js b/js/src/tests/non262/Iterator/prototype/toArray/name.js new file mode 100644 index 0000000000..b382c3a3a6 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/toArray/name.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +/*--- + `name` property of Iterator.prototype.toArray. +---*/ + +const propDesc = Reflect.getOwnPropertyDescriptor(Iterator.prototype.toArray, 'name'); +assertEq(propDesc.value, 'toArray'); +assertEq(propDesc.writable, false); +assertEq(propDesc.enumerable, false); +assertEq(propDesc.configurable, true); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/toArray/next-throws.js b/js/src/tests/non262/Iterator/prototype/toArray/next-throws.js new file mode 100644 index 0000000000..c93ecdd324 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/toArray/next-throws.js @@ -0,0 +1,14 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +class TestIterator extends Iterator { + next() { + throw new Error(); + } +} + +const iter = new TestIterator(); + +assertThrowsInstanceOf(() => iter.toArray(), Error); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/toArray/proxy.js b/js/src/tests/non262/Iterator/prototype/toArray/proxy.js new file mode 100644 index 0000000000..83024eeb8a --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/toArray/proxy.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally +// +// This test checks that %Iterator.prototype%.toArray only gets the `next` method off of the +// iterator once, and never accesses the @@iterator property. +const log = []; +const handlerProxy = new Proxy({}, { + get: (target, key, receiver) => (...args) => { + log.push(`${key}: ${args[1]?.toString()}`); + return Reflect[key](...args); + }, +}); + +class Counter extends Iterator { + value = 0; + next() { + const value = this.value; + if (value < 2) { + this.value = value + 1; + return {done: false, value}; + } + return {done: true}; + } +} + +const iter = new Proxy(new Counter(), handlerProxy); +const array = iter.toArray(); + +assertEq( + log.join('\n'), + `get: toArray +get: next +get: value +set: value +getOwnPropertyDescriptor: value +defineProperty: value +get: value +set: value +getOwnPropertyDescriptor: value +defineProperty: value +get: value` +); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/toArray/this-not-iterator-throws.js b/js/src/tests/non262/Iterator/prototype/toArray/this-not-iterator-throws.js new file mode 100644 index 0000000000..1442d22557 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/toArray/this-not-iterator-throws.js @@ -0,0 +1,8 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +assertThrowsInstanceOf(Iterator.prototype.toArray.bind(undefined), TypeError); +assertThrowsInstanceOf(Iterator.prototype.toArray.bind({}), TypeError); +assertThrowsInstanceOf(Iterator.prototype.toArray.bind({next: 0}), TypeError); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/toArray/toArray.js b/js/src/tests/non262/Iterator/prototype/toArray/toArray.js new file mode 100644 index 0000000000..29c99525fb --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/toArray/toArray.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +const iter = [1, 2, 3].values(); +assertEq(Array.isArray(iter), false); + +const array = iter.toArray(); +assertEq(Array.isArray(array), true); +assertEq(array.length, 3); + +const expected = [1, 2, 3]; +for (const item of array) { + const expect = expected.shift(); + assertEq(item, expect); +} + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Iterator/prototype/toArray/value-throws-iterator-not-closed.js b/js/src/tests/non262/Iterator/prototype/toArray/value-throws-iterator-not-closed.js new file mode 100644 index 0000000000..ca56de8a66 --- /dev/null +++ b/js/src/tests/non262/Iterator/prototype/toArray/value-throws-iterator-not-closed.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Iterator')) -- Iterator is not enabled unconditionally + +class TestError extends Error {} +class TestIterator extends Iterator { + next() { + return new Proxy({done: false}, {get: (target, key, receiver) => { + if (key === 'value') + throw new TestError(); + return 0; + }}); + } + + closed = false; + return() { + closed = true; + } +} + +const iterator = new TestIterator(); +assertEq(iterator.closed, false, 'iterator starts unclosed'); +assertThrowsInstanceOf(() => iterator.toArray(), TestError); +assertEq(iterator.closed, false, 'iterator remains unclosed'); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/JSON/browser.js b/js/src/tests/non262/JSON/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/JSON/cyclic-stringify-unrelated.js b/js/src/tests/non262/JSON/cyclic-stringify-unrelated.js new file mode 100644 index 0000000000..127c2ca600 --- /dev/null +++ b/js/src/tests/non262/JSON/cyclic-stringify-unrelated.js @@ -0,0 +1,39 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 1197097; +var summary = "JSON.stringify shouldn't use context-wide cycle detection"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var arr; + +// Nested yet separate JSON.stringify is okay. +arr = [{}]; +assertEq(JSON.stringify(arr, function(k, v) { + assertEq(JSON.stringify(arr), "[{}]"); + return v; +}), "[{}]"); + +// SpiderMonkey censors cycles in array-joining. This mechanism must not +// interfere with the cycle detection in JSON.stringify. +arr = [{ + toString: function() { + var s = JSON.stringify(arr); + assertEq(s, "[{}]"); + return s; + } +}]; +assertEq(arr.join(), "[{}]"); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/cyclic-stringify.js b/js/src/tests/non262/JSON/cyclic-stringify.js new file mode 100644 index 0000000000..5eb6273a97 --- /dev/null +++ b/js/src/tests/non262/JSON/cyclic-stringify.js @@ -0,0 +1,100 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 578273; +var summary = + "ES5: Properly detect cycles in JSON.stringify (throw TypeError, check for " + + "cycles rather than imprecisely rely on recursion limits)"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +// objects + +var count = 0; +var desc = + { + get: function() { count++; return obj; }, + enumerable: true, + configurable: true + }; +var obj = Object.defineProperty({ p1: 0 }, "p2", desc); + +try +{ + var str = JSON.stringify(obj); + assertEq(false, true, "should have thrown, got " + str); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, + "wrong error type: " + e.constructor.name); + assertEq(count, 1, + "cyclic data structures not detected immediately"); +} + +count = 0; +var obj2 = Object.defineProperty({}, "obj", desc); +try +{ + var str = JSON.stringify(obj2); + assertEq(false, true, "should have thrown, got " + str); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, + "wrong error type: " + e.constructor.name); + assertEq(count, 2, + "cyclic data structures not detected immediately"); +} + + +// arrays + +var count = 0; +var desc = + { + get: function() { count++; return arr; }, + enumerable: true, + configurable: true + }; +var arr = Object.defineProperty([], "0", desc); + +try +{ + var str = JSON.stringify(arr); + assertEq(false, true, "should have thrown, got " + str); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, + "wrong error type: " + e.constructor.name); + assertEq(count, 1, + "cyclic data structures not detected immediately"); +} + +count = 0; +var arr2 = Object.defineProperty([], "0", desc); +try +{ + var str = JSON.stringify(arr2); + assertEq(false, true, "should have thrown, got " + str); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, + "wrong error type: " + e.constructor.name); + assertEq(count, 2, + "cyclic data structures not detected immediately"); +} + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/immutable-reviver.js b/js/src/tests/non262/JSON/immutable-reviver.js new file mode 100644 index 0000000000..b9f4abc31c --- /dev/null +++ b/js/src/tests/non262/JSON/immutable-reviver.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty("Record")) + +const values = []; + +const result = JSON.parseImmutable('{"x":1,"a":[1,2,{},[]]}', function (k, v) { + values.push(#[k, v]); + return v; +}); + +assertEq(result, #{x: 1, a: #[1, 2, #{}, #[]]}); + +const next = () => values.shift(); +assertEq(next(), #["x", 1]); +assertEq(next(), #["0", 1]); +assertEq(next(), #["1", 2]); +assertEq(next(), #["2", #{}]); +assertEq(next(), #["3", #[]]); +assertEq(next(), #["a", #[1, 2, #{}, #[]]]); +assertEq(next(), #["", result]); +assertEq(values.length, 0); + +if (typeof reportCompare === "function") reportCompare(0, 0); diff --git a/js/src/tests/non262/JSON/immutable.js b/js/src/tests/non262/JSON/immutable.js new file mode 100644 index 0000000000..e84dc3612a --- /dev/null +++ b/js/src/tests/non262/JSON/immutable.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty("Record")) + +assertEq( + JSON.parseImmutable('{"x":1,"a":[1,2,{},[]]}'), + #{ x: 1, a: #[1, 2, #{}, #[]] } +); + +assertEq( + JSON.parseImmutable('{"a":1,"a":2}'), + #{ a: 2 } +); + +if (typeof reportCompare === "function") reportCompare(0, 0); diff --git a/js/src/tests/non262/JSON/parse-arguments.js b/js/src/tests/non262/JSON/parse-arguments.js new file mode 100644 index 0000000000..d7ed6d73bd --- /dev/null +++ b/js/src/tests/non262/JSON/parse-arguments.js @@ -0,0 +1,30 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +var gTestfile = 'parse-arguments.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 653847; +var summary = "JSON.parse handling of omitted arguments"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +try +{ + var r = JSON.parse(); + throw new Error("didn't throw, returned " + r); +} +catch (e) +{ + assertEq(e instanceof SyntaxError, true, "expected syntax error, got: " + e); +} + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/parse-array-gc.js b/js/src/tests/non262/JSON/parse-array-gc.js new file mode 100644 index 0000000000..f617ea66dc --- /dev/null +++ b/js/src/tests/non262/JSON/parse-array-gc.js @@ -0,0 +1,34 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +var gTestfile = "parse-array-gc.js"; +//----------------------------------------------------------------------------- +var BUGNUMBER = 852563; +var summary = + "IdValuePair::value should be initialized to avoid GC sequence-point issues"; + +print(BUGNUMBER + ": " + summary); + +print("Note: You must run this test under valgrind to be certain it passes"); + +/************** + * BEGIN TEST * + **************/ + +var x; + +if (typeof gczeal === "function") + gczeal(2, 1); +x = JSON.parse('{"foo":[]}'); +Object.getPrototypeOf(x.foo) == Array.prototype; +x = JSON.parse('{"foo":[], "bar":[]}'); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +if (typeof gczeal === "function") + gczeal(0); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/parse-crockford-01.js b/js/src/tests/non262/JSON/parse-crockford-01.js new file mode 100644 index 0000000000..5be9e90edb --- /dev/null +++ b/js/src/tests/non262/JSON/parse-crockford-01.js @@ -0,0 +1,121 @@ +var str = + '[\n' + + ' "JSON Test Pattern pass1",\n' + + ' {"object with 1 member":["array with 1 element"]},\n' + + ' {},\n' + + ' [],\n' + + ' -42,\n' + + ' true,\n' + + ' false,\n' + + ' null,\n' + + ' {\n' + + ' "integer": 1234567890,\n' + + ' "real": -9876.543210,\n' + + ' "e": 0.123456789e-12,\n' + + ' "E": 1.234567890E+34,\n' + + ' "": 23456789012E66,\n' + + ' "zero": 0,\n' + + ' "one": 1,\n' + + ' "space": " ",\n' + + ' "quote": "\\"",\n' + + ' "backslash": "\\\\",\n' + + ' "controls": "\\b\\f\\n\\r\\t",\n' + + ' "slash": "/ & \\/",\n' + + ' "alpha": "abcdefghijklmnopqrstuvwyz",\n' + + ' "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ",\n' + + ' "digit": "0123456789",\n' + + ' "0123456789": "digit",\n' + + ' "special": "`1~!@#$%^&*()_+-={\':[,]}|;.?",\n' + + ' "hex": "\\u0123\\u4567\\u89AB\\uCDEF\\uabcd\\uef4A",\n' + + ' "true": true,\n' + + ' "false": false,\n' + + ' "null": null,\n' + + ' "array":[ ],\n' + + ' "object":{ },\n' + + ' "address": "50 St. James Street",\n' + + ' "url": "http://www.JSON.org/",\n' + + ' "comment": "// /* */": " ",\n' + + ' " s p a c e d " :[1,2 , 3\n' + + '\n' + + ',\n' + + '\n' + + '4 , 5 , 6 ,7 ],"compact":[1,2,3,4,5,6,7],\n' + + ' "jsontext": "{\\"object with 1 member\\":[\\"array with 1 element\\"]}",\n' + + ' "quotes": "" \\u0022 %22 0x22 034 "",\n' + + ' "\\/\\\\\\"\\uCAFE\\uBABE\\uAB98\\uFCDE\\ubcda\\uef4A\\b\\f\\n\\r\\t`1~!@#$%^&*()_+-=[]{}|;:\',./<>?"\n' + + ': "A key can be any string"\n' + + ' },\n' + + ' 0.5 ,98.6\n' + + ',\n' + + '99.44\n' + + ',\n' + + '\n' + + '1066,\n' + + '1e1,\n' + + '0.1e1,\n' + + '1e-1,\n' + + '1e00,2e+00,2e-00\n' + + ',"rosebud"]\n'; + +var x = JSON.parse(str); + +assertEq(x[0], "JSON Test Pattern pass1"); +assertEq(x[1]["object with 1 member"][0], "array with 1 element"); +assertEq(x[2].constructor, Object); +assertEq(x[3].constructor, Array); +assertEq(x[4], -42); +assertEq(x[5], true); +assertEq(x[6], false); +assertEq(x[7], null); +assertEq(x[8].constructor, Object); +assertEq(x[8]["integer"], 1234567890); +assertEq(x[8]["real"], -9876.543210); +assertEq(x[8]["e"], 0.123456789e-12); +assertEq(x[8]["E"], 1.234567890E+34); +assertEq(x[8][""], 23456789012E66); +assertEq(x[8]["zero"], 0); +assertEq(x[8]["one"], 1); +assertEq(x[8]["space"], " "); +assertEq(x[8]["quote"], "\""); +assertEq(x[8]["backslash"], "\\"); +assertEq(x[8]["controls"], "\b\f\n\r\t"); +assertEq(x[8]["slash"], "/ & /"); +assertEq(x[8]["alpha"], "abcdefghijklmnopqrstuvwyz"); +assertEq(x[8]["ALPHA"], "ABCDEFGHIJKLMNOPQRSTUVWYZ"); +assertEq(x[8]["digit"], "0123456789"); +assertEq(x[8]["0123456789"], "digit"); +assertEq(x[8]["special"], "`1~!@#$%^&*()_+-={':[,]}|;.?"); +assertEq(x[8]["hex"], "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A"); +assertEq(x[8]["true"], true); +assertEq(x[8]["false"], false); +assertEq(x[8]["null"], null); +assertEq(x[8]["array"].length, 0); +assertEq(x[8]["object"].constructor, Object); +assertEq(x[8]["address"], "50 St. James Street"); +assertEq(x[8]["url"], "http://www.JSON.org/"); +assertEq(x[8]["comment"], "// /* */"], " "); +assertEq(x[8][" s p a c e d "].length, 7); +assertEq(x[8]["compact"].length, 7); +assertEq(x[8]["jsontext"], "{\"object with 1 member\":[\"array with 1 element\"]}"); +assertEq(x[8]["quotes"], "" \u0022 %22 0x22 034 ""); +assertEq(x[8]["\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?"], "A key can be any string"); +assertEq(x[9], 0.5); +assertEq(x[10], 98.6); +assertEq(x[11], 99.44); +assertEq(x[12], 1066); +assertEq(x[13], 1e1); +assertEq(x[14], 0.1e1); +assertEq(x[15], 1e-1); +assertEq(x[16], 1e00); +assertEq(x[17], 2e+00); +assertEq(x[18], 2e-00); +assertEq(x[19], "rosebud"); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/parse-mega-huge-array.js b/js/src/tests/non262/JSON/parse-mega-huge-array.js new file mode 100644 index 0000000000..8f1c192c1e --- /dev/null +++ b/js/src/tests/non262/JSON/parse-mega-huge-array.js @@ -0,0 +1,28 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +var gTestfile = 'parse-mega-huge-array.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 667527; +var summary = "JSON.parse should parse arrays of essentially unlimited size"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var body = "0,"; +for (var i = 0; i < 21; i++) + body = body + body; +var str = '[' + body + '0]'; + +var arr = JSON.parse(str); +assertEq(arr.length, Math.pow(2, 21) + 1); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/parse-number-syntax.js b/js/src/tests/non262/JSON/parse-number-syntax.js new file mode 100644 index 0000000000..42dbbe0b45 --- /dev/null +++ b/js/src/tests/non262/JSON/parse-number-syntax.js @@ -0,0 +1,32 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +testJSON('-', true); +testJSON('+', true); +testJSON('-f', true); +testJSON('+f', true); +testJSON('00', true); +testJSON('01', true); +testJSON('1.', true); +testJSON('1.0e', true); +testJSON('1.0e+', true); +testJSON('1.0e-', true); +testJSON('1.0e+z', true); +testJSON('1.0e-z', true); +testJSON('1.0ee', true); +testJSON('1.e1', true); +testJSON('1.e+1', true); +testJSON('1.e-1', true); +testJSON('.', true); +testJSON('.1', true); +testJSON('.1e', true); +testJSON('.1e1', true); +testJSON('.1e+1', true); +testJSON('.1e-1', true); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/parse-octal-syntax-error.js b/js/src/tests/non262/JSON/parse-octal-syntax-error.js new file mode 100644 index 0000000000..f7b0a13a6f --- /dev/null +++ b/js/src/tests/non262/JSON/parse-octal-syntax-error.js @@ -0,0 +1,8 @@ +testJSON('{"Numbers cannot have leading zeroes": 013}', true); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/parse-primitives.js b/js/src/tests/non262/JSON/parse-primitives.js new file mode 100644 index 0000000000..450e1a6577 --- /dev/null +++ b/js/src/tests/non262/JSON/parse-primitives.js @@ -0,0 +1,62 @@ +var x; + +// check an empty object, just for sanity +var emptyObject = "{}"; +x = JSON.parse(emptyObject); +assertEq(typeof x, "object"); +assertEq(x instanceof Object, true); + +x = JSON.parse(emptyObject); +assertEq(typeof x, "object"); + +// booleans and null +x = JSON.parse("true"); +assertEq(x, true); + +x = JSON.parse("true "); +assertEq(x, true); + +x = JSON.parse("false"); +assertEq(x, false); + +x = JSON.parse(" null "); +assertEq(x, null); + +// numbers +x = JSON.parse("1234567890"); +assertEq(x, 1234567890); + +x = JSON.parse("-9876.543210"); +assertEq(x, -9876.543210); + +x = JSON.parse("0.123456789e-12"); +assertEq(x, 0.123456789e-12); + +x = JSON.parse("1.234567890E+34"); +assertEq(x, 1.234567890E+34); + +x = JSON.parse(" 23456789012E66 \r\r\r\r \n\n\n\n "); +assertEq(x, 23456789012E66); + +// strings +x = JSON.parse('"foo"'); +assertEq(x, "foo"); + +x = JSON.parse('"\\r\\n"'); +assertEq(x, "\r\n"); + +x = JSON.parse(' "\\uabcd\uef4A"'); +assertEq(x, "\uabcd\uef4A"); + +x = JSON.parse('"\\uabcd" '); +assertEq(x, "\uabcd"); + +x = JSON.parse('"\\f"'); +assertEq(x, "\f"); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/parse-reviver-array-delete.js b/js/src/tests/non262/JSON/parse-reviver-array-delete.js new file mode 100644 index 0000000000..c343058785 --- /dev/null +++ b/js/src/tests/non262/JSON/parse-reviver-array-delete.js @@ -0,0 +1,89 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +var gTestfile = 'parse-reviver-array-delete.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 999999; +var summary = "JSON.parse with a reviver which elides array elements"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +/* + * The reviver deletes all properties from the to-be-returned array. Thus + * stringification reveals properties on the prototype chain -- but there are + * none, so this result is unsurprising. + */ +assertEq(JSON.parse('[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0]', + function revive(k, v) + { + if (k === "") + return v; + return undefined; + }) + "", + ",,,,,,,,,,,,,,,,,,,"); + +/* + * Now let's try a reviver that deletes every property but a mega-huge one. + */ +var str = "["; +var expected = ""; +var expected2 = ""; +for (var i = 0; i < 2048; i++) +{ + str += "1,"; + if (i === 2047) + { + expected += "1"; + expected2 += "1"; + } + if (i === 3) + expected2 += "17"; + expected += ","; + expected2 += ","; +} +str += "1]"; + +assertEq(JSON.parse(str, + function reviver(k, v) + { + if (k === "" || k === "2047") + return v; + return undefined; + }) + "", + expected); + + +Array.prototype[3] = 17; + +/* Now, with a property on the prototype chain, it'll show through. */ +assertEq(JSON.parse('[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0]', + function revive(k, v) + { + if (k === "") + return v; + return undefined; + }) + "", + ",,,17,,,,,,,,,,,,,,,,"); + + +/* And here too. */ +assertEq(JSON.parse(str, + function reviver(k, v) + { + if (k === "" || k === "2047") + return v; + return undefined; + }) + "", + expected2); + + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/parse-reviver.js b/js/src/tests/non262/JSON/parse-reviver.js new file mode 100644 index 0000000000..41e3daf704 --- /dev/null +++ b/js/src/tests/non262/JSON/parse-reviver.js @@ -0,0 +1,45 @@ +function doubler(k, v) +{ + assertEq(typeof k, "string"); + + if (typeof v == "number") + return 2 * v; + + return v; +} + +var x = JSON.parse('{"a":5,"b":6}', doubler); +assertEq(x.hasOwnProperty('a'), true); +assertEq(x.hasOwnProperty('b'), true); +assertEq(x.a, 10); +assertEq(x.b, 12); + +x = JSON.parse('[3, 4, 5]', doubler); +assertEq(x[0], 6); +assertEq(x[1], 8); +assertEq(x[2], 10); + +// make sure reviver isn't called after a failed parse +var called = false; +function dontCallMe(k, v) +{ + called = true; +} + +try +{ + JSON.parse('{{{{{{{}}}}', dontCallMe); + throw new Error("didn't throw?"); +} +catch (e) +{ + assertEq(e instanceof SyntaxError, true, "wrong exception: " + e); +} +assertEq(called, false); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/parse-syntax-errors-01.js b/js/src/tests/non262/JSON/parse-syntax-errors-01.js new file mode 100644 index 0000000000..cbb49b0eb7 --- /dev/null +++ b/js/src/tests/non262/JSON/parse-syntax-errors-01.js @@ -0,0 +1,13 @@ +testJSON("{}...", true); +testJSON('{"foo": truBBBB}', true); +testJSON('{foo: truBBBB}', true); +testJSON('{"foo": undefined}', true); +testJSON('{"foo": ]', true); +testJSON('{"foo', true); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/parse-syntax-errors-02.js b/js/src/tests/non262/JSON/parse-syntax-errors-02.js new file mode 100644 index 0000000000..b304e07ca0 --- /dev/null +++ b/js/src/tests/non262/JSON/parse-syntax-errors-02.js @@ -0,0 +1,43 @@ +testJSON('"Unterminated string literal', true); +testJSON('["Unclosed array"', true); +testJSON('{unquoted_key: "keys must be quoted"}', true); +testJSON('["extra comma",]', true); +testJSON('["double extra comma",,]', true); +testJSON('[ , "<-- missing value"]', true); +testJSON('["Comma after the close"],', true); +testJSON('["Extra close"]]', true); +testJSON('{"Extra comma": true,}', true); +testJSON('{"Extra value after close": true} "misplaced quoted value"', true); +testJSON('{"Illegal expression": 1 + 2}', true); +testJSON('{"Illegal invocation": alert()}', true); +testJSON('{"Numbers cannot be hex": 0x14}', true); +testJSON('["Illegal backslash escape: \\x15"]', true); +testJSON('[\\naked]', true); +testJSON('["Illegal backslash escape: \\017"]', true); +testJSON('{"Missing colon" null}', true); +testJSON('{"Double colon":: null}', true); +testJSON('{"Comma instead of colon", null}', true); +testJSON('["Colon instead of comma": false]', true); +testJSON('["Bad value", truth]', true); +testJSON("['single quote']", true); +testJSON('[" tab character in string "]', true); +testJSON('["tab\\ character\\ in\\ string\\ "]', true); +testJSON('["line\rbreak"]', true); +testJSON('["line\nbreak"]', true); +testJSON('["line\r\nbreak"]', true); +testJSON('["line\\\rbreak"]', true); +testJSON('["line\\\nbreak"]', true); +testJSON('["line\\\r\nbreak"]', true); +testJSON('[0e]', true); +testJSON('[0e+]', true); +testJSON('[0e+-1]', true); +testJSON('{"Comma instead of closing brace": true,', true); +testJSON('["mismatch"}', true); +testJSON('0{', true); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/parse-syntax-errors-03.js b/js/src/tests/non262/JSON/parse-syntax-errors-03.js new file mode 100644 index 0000000000..5cdf585a40 --- /dev/null +++ b/js/src/tests/non262/JSON/parse-syntax-errors-03.js @@ -0,0 +1,55 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +testJSON('[', true); +testJSON('[1', true); +testJSON('[1,]', true); +testJSON('[1,{', true); +testJSON('[1,}', true); +testJSON('[1,{]', true); +testJSON('[1,}]', true); +testJSON('[1,{"', true); +testJSON('[1,}"', true); +testJSON('[1,{"\\', true); +testJSON('[1,}"\\', true); +testJSON('[1,"', true); +testJSON('[1,"\\', true); + +testJSON('{', true); +testJSON('{1', true); +testJSON('{,', true); +testJSON('{"', true); +testJSON('{"\\', true); +testJSON('{"\\u', true); +testJSON('{"\\uG', true); +testJSON('{"\\u0', true); +testJSON('{"\\u01', true); +testJSON('{"\\u012', true); +testJSON('{"\\u0123', true); +testJSON('{"\\u0123"', true); +testJSON('{"a"', true); +testJSON('{"a"}', true); +testJSON('{"a":', true); +testJSON('{"a",}', true); +testJSON('{"a":}', true); +testJSON('{"a":,}', true); +testJSON('{"a":5,}', true); +testJSON('{"a":5,[', true); +testJSON('{"a":5,"', true); +testJSON('{"a":5,"', true); +testJSON('{"a":5,"\\', true); +testJSON("a[false ]".substring(1, 7) /* "[false" */, true); + +testJSON('this', true); + +testJSON('[1,{}]', false); +testJSON('{}', false); +testJSON('{"a":5}', false); +testJSON('{"\\u0123":5}', false); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/parse-with-source.js b/js/src/tests/non262/JSON/parse-with-source.js new file mode 100644 index 0000000000..96e9550706 --- /dev/null +++ b/js/src/tests/non262/JSON/parse-with-source.js @@ -0,0 +1,49 @@ +// |reftest| skip-if(!(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration('json-parse-with-source'))) shell-option(--enable-json-parse-with-source) + +var actual; + +function reviver(key, value, context) { + assertEq(arguments.length, 3); + assertEq("source" in context, true); + actual = context["source"]; +} + +let tests = [ + // STRINGS + {input: '""', expected: '""'}, + {input: '"str"', expected: '"str"'}, + {input: '"str" ', expected: '"str"'}, + {input: ' "str" ', expected: '"str"'}, + {input: ' " str"', expected: '" str"'}, + {input: '"\uD83D\uDE0A\u2764\u2FC1"', expected: '"\uD83D\uDE0A\u2764\u2FC1"'}, + // NUMBERS + {input: '1', expected: '1'}, + {input: ' 1', expected: '1'}, + {input: '4.2', expected: '4.2'}, + {input: '4.2 ', expected: '4.2'}, + {input: '4.2000 ', expected: '4.2000'}, + {input: '4e2000 ', expected: '4e2000'}, + {input: '4.4e2000 ', expected: '4.4e2000'}, + {input: '9007199254740999', expected: '9007199254740999'}, + {input: '-31', expected: '-31'}, + {input: '-3.1', expected: '-3.1'}, + {input: ' -31 ', expected: '-31'}, + // BOOLEANS + {input: 'true', expected: 'true'}, + {input: 'true ', expected: 'true'}, + {input: 'false', expected: 'false'}, + {input: ' false', expected: 'false'}, + // NULL + {input: 'null', expected: 'null'}, + {input: ' null', expected: 'null'}, + {input: '\tnull ', expected: 'null'}, + {input: 'null\t', expected: 'null'}, +]; +for (const test of tests) { + print("Testing " + JSON.stringify(test)); + JSON.parse(test.input, reviver); + assertEq(actual, test.expected); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0); \ No newline at end of file diff --git a/js/src/tests/non262/JSON/parse.js b/js/src/tests/non262/JSON/parse.js new file mode 100644 index 0000000000..ff9dc51a79 --- /dev/null +++ b/js/src/tests/non262/JSON/parse.js @@ -0,0 +1,175 @@ +function assertIsObject(x) +{ + assertEq(typeof x, "object"); + assertEq(x instanceof Object, true); +} + +function assertIsArray(x) +{ + assertIsObject(x); + assertEq(Array.isArray(x), true); + assertEq(Object.getPrototypeOf(x), Array.prototype); + assertEq(x instanceof Array, true); + assertEq(x.constructor, Array); +} + +var x; +var props; + +// empty object +x = JSON.parse("{}"); +assertIsObject(x); +assertEq(Object.getOwnPropertyNames(x).length, 0); + +// empty array +x = JSON.parse("[]"); +assertIsArray(x); +assertEq(x.length, 0); + +// one element array +x = JSON.parse("[[]]"); +assertIsArray(x); +assertEq(x.length, 1); +assertIsArray(x[0]); +assertEq(x[0].length, 0); + +// multiple arrays +x = JSON.parse("[[],[],[]]"); +assertIsArray(x); +assertEq(x.length, 3); +assertIsArray(x[0]); +assertEq(x[0].length, 0); +assertIsArray(x[1]); +assertEq(x[1].length, 0); +assertIsArray(x[2]); +assertEq(x[2].length, 0); + +// array key/value +x = JSON.parse('{"foo":[]}'); +assertIsObject(x); +props = Object.getOwnPropertyNames(x); +assertEq(props.length, 1); +assertEq(props[0], "foo"); +assertIsArray(x.foo); +assertEq(x.foo.length, 0); + +x = JSON.parse('{"foo":[], "bar":[]}'); +assertIsObject(x); +props = Object.getOwnPropertyNames(x).sort(); +assertEq(props.length, 2); +assertEq(props[0], "bar"); +assertEq(props[1], "foo"); +assertIsArray(x.foo); +assertEq(x.foo.length, 0); +assertIsArray(x.bar); +assertEq(x.bar.length, 0); + +// nesting +x = JSON.parse('{"foo":[{}]}'); +assertIsObject(x); +props = Object.getOwnPropertyNames(x); +assertEq(props.length, 1); +assertEq(props[0], "foo"); +assertIsArray(x.foo); +assertEq(x.foo.length, 1); +assertIsObject(x.foo[0]); +assertEq(Object.getOwnPropertyNames(x.foo[0]).length, 0); + +x = JSON.parse('{"foo":[{"foo":[{"foo":{}}]}]}'); +assertIsObject(x.foo[0].foo[0].foo); + +x = JSON.parse('{"foo":[{"foo":[{"foo":[]}]}]}'); +assertIsArray(x.foo[0].foo[0].foo); + +// strings +x = JSON.parse('{"foo":"bar"}'); +assertIsObject(x); +props = Object.getOwnPropertyNames(x); +assertEq(props.length, 1); +assertEq(props[0], "foo"); +assertEq(x.foo, "bar"); + +x = JSON.parse('["foo", "bar", "baz"]'); +assertIsArray(x); +assertEq(x.length, 3); +assertEq(x[0], "foo"); +assertEq(x[1], "bar"); +assertEq(x[2], "baz"); + +// numbers +x = JSON.parse('{"foo":5.5, "bar":5}'); +assertIsObject(x); +props = Object.getOwnPropertyNames(x).sort(); +assertEq(props.length, 2); +assertEq(props[0], "bar"); +assertEq(props[1], "foo"); +assertEq(x.foo, 5.5); +assertEq(x.bar, 5); + +// keywords +x = JSON.parse('{"foo": true, "bar":false, "baz":null}'); +assertIsObject(x); +props = Object.getOwnPropertyNames(x).sort(); +assertEq(props.length, 3); +assertEq(props[0], "bar"); +assertEq(props[1], "baz"); +assertEq(props[2], "foo"); +assertEq(x.foo, true); +assertEq(x.bar, false); +assertEq(x.baz, null); + +// short escapes +x = JSON.parse('{"foo": "\\"", "bar":"\\\\", "baz":"\\b","qux":"\\f", "quux":"\\n", "quuux":"\\r","quuuux":"\\t"}'); +props = Object.getOwnPropertyNames(x).sort(); +assertEq(props.length, 7); +assertEq(props[0], "bar"); +assertEq(props[1], "baz"); +assertEq(props[2], "foo"); +assertEq(props[3], "quuuux"); +assertEq(props[4], "quuux"); +assertEq(props[5], "quux"); +assertEq(props[6], "qux"); +assertEq(x.foo, '"'); +assertEq(x.bar, '\\'); +assertEq(x.baz, '\b'); +assertEq(x.qux, '\f'); +assertEq(x.quux, "\n"); +assertEq(x.quuux, "\r"); +assertEq(x.quuuux, "\t"); + +// unicode escape +x = JSON.parse('{"foo":"hmm\\u006dmm"}'); +assertIsObject(x); +props = Object.getOwnPropertyNames(x); +assertEq(props.length, 1); +assertEq(props[0], "foo"); +assertEq("hmm\u006dmm", x.foo); + +x = JSON.parse('{"hmm\\u006dmm":"foo"}'); +assertIsObject(x); +props = Object.getOwnPropertyNames(x); +assertEq(props.length, 1); +assertEq(props[0], "hmmmmm"); +assertEq(x.hmm\u006dmm, "foo"); + +// miscellaneous +x = JSON.parse('{"JSON Test Pattern pass3": {"The outermost value": "must be an object or array.","In this test": "It is an object." }}'); +assertIsObject(x); +props = Object.getOwnPropertyNames(x); +assertEq(props.length, 1); +assertEq(props[0], "JSON Test Pattern pass3"); +assertIsObject(x["JSON Test Pattern pass3"]); +props = Object.getOwnPropertyNames(x["JSON Test Pattern pass3"]).sort(); +assertEq(props.length, 2); +assertEq(props[0], "In this test"); +assertEq(props[1], "The outermost value"); +assertEq(x["JSON Test Pattern pass3"]["The outermost value"], + "must be an object or array."); +assertEq(x["JSON Test Pattern pass3"]["In this test"], "It is an object."); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/regress-458959.js b/js/src/tests/non262/JSON/regress-458959.js new file mode 100644 index 0000000000..648918e8ed --- /dev/null +++ b/js/src/tests/non262/JSON/regress-458959.js @@ -0,0 +1,29 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 458959; +var summary = 'this.JSON should not be enumerable'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + for (var i in this) + { + if (i.toString() == 'JSON') + actual = i; + } + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/JSON/regress-459293.js b/js/src/tests/non262/JSON/regress-459293.js new file mode 100644 index 0000000000..fbd46589ca --- /dev/null +++ b/js/src/tests/non262/JSON/regress-459293.js @@ -0,0 +1,25 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: Robert Sayre + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 459293; +var summary = 'Allow redeclaration of JSON'; +var actual = ''; +var expect = ''; + + printBugNumber(BUGNUMBER); + printStatus (summary); + + try + { + eval('var JSON = "foo";'); + } + catch(ex) + { + actual = ex + ''; + } + reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/JSON/shell.js b/js/src/tests/non262/JSON/shell.js new file mode 100644 index 0000000000..00f3243dac --- /dev/null +++ b/js/src/tests/non262/JSON/shell.js @@ -0,0 +1,110 @@ +function testJSON(str, expectSyntaxError) +{ + // Leading and trailing whitespace never affect parsing, so test the string + // multiple times with and without whitespace around it as it's easy and can + // potentially detect bugs. + + // Try the provided string + try + { + JSON.parse(str); + reportCompare(false, expectSyntaxError, + "string <" + str + "> " + + "should" + (expectSyntaxError ? "n't" : "") + " " + + "have parsed as JSON"); + } + catch (e) + { + if (!(e instanceof SyntaxError)) + { + reportCompare(true, false, + "parsing string <" + str + "> threw a non-SyntaxError " + + "exception: " + e); + } + else + { + reportCompare(true, expectSyntaxError, + "string <" + str + "> " + + "should" + (expectSyntaxError ? "n't" : "") + " " + + "have parsed as JSON, exception: " + e); + } + } + + // Now try the provided string with trailing whitespace + try + { + JSON.parse(str + " "); + reportCompare(false, expectSyntaxError, + "string <" + str + " > " + + "should" + (expectSyntaxError ? "n't" : "") + " " + + "have parsed as JSON"); + } + catch (e) + { + if (!(e instanceof SyntaxError)) + { + reportCompare(true, false, + "parsing string <" + str + " > threw a non-SyntaxError " + + "exception: " + e); + } + else + { + reportCompare(true, expectSyntaxError, + "string <" + str + " > " + + "should" + (expectSyntaxError ? "n't" : "") + " " + + "have parsed as JSON, exception: " + e); + } + } + + // Now try the provided string with leading whitespace + try + { + JSON.parse(" " + str); + reportCompare(false, expectSyntaxError, + "string < " + str + "> " + + "should" + (expectSyntaxError ? "n't" : "") + " " + + "have parsed as JSON"); + } + catch (e) + { + if (!(e instanceof SyntaxError)) + { + reportCompare(true, false, + "parsing string < " + str + "> threw a non-SyntaxError " + + "exception: " + e); + } + else + { + reportCompare(true, expectSyntaxError, + "string < " + str + "> " + + "should" + (expectSyntaxError ? "n't" : "") + " " + + "have parsed as JSON, exception: " + e); + } + } + + // Now try the provided string with whitespace surrounding it + try + { + JSON.parse(" " + str + " "); + reportCompare(false, expectSyntaxError, + "string < " + str + " > " + + "should" + (expectSyntaxError ? "n't" : "") + " " + + "have parsed as JSON"); + } + catch (e) + { + if (!(e instanceof SyntaxError)) + { + reportCompare(true, false, + "parsing string < " + str + " > threw a non-SyntaxError " + + "exception: " + e); + } + else + { + reportCompare(true, expectSyntaxError, + "string < " + str + " > " + + "should" + (expectSyntaxError ? "n't" : "") + " " + + "have parsed as JSON, exception: " + e); + } + } +} diff --git a/js/src/tests/non262/JSON/small-codepoints.js b/js/src/tests/non262/JSON/small-codepoints.js new file mode 100644 index 0000000000..6afa5f8ce8 --- /dev/null +++ b/js/src/tests/non262/JSON/small-codepoints.js @@ -0,0 +1,16 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +var gTestfile = 'small-codepoints.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 554079; +var summary = 'JSON.parse should reject U+0000 through U+001F'; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +for (var i = 0; i <= 0x1F; i++) + testJSON('["a' + String.fromCharCode(i) + 'c"]', true); diff --git a/js/src/tests/non262/JSON/stringify-boxed-primitives.js b/js/src/tests/non262/JSON/stringify-boxed-primitives.js new file mode 100644 index 0000000000..0769c2ec6f --- /dev/null +++ b/js/src/tests/non262/JSON/stringify-boxed-primitives.js @@ -0,0 +1,127 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +var gTestfile = 'stringify-boxed-primitives.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 584909; +var summary = "Stringification of Boolean/String/Number objects"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function redefine(obj, prop, fun) +{ + var desc = + { value: fun, writable: true, configurable: true, enumerable: false }; + Object.defineProperty(obj, prop, desc); +} + +assertEq(JSON.stringify(new Boolean(false)), "false"); + +assertEq(JSON.stringify(new Number(5)), "5"); + +assertEq(JSON.stringify(new String("foopy")), '"foopy"'); + + +var numToString = Number.prototype.toString; +var numValueOf = Number.prototype.valueOf; +var objToString = Object.prototype.toString; +var objValueOf = Object.prototype.valueOf; +var boolToString = Boolean.prototype.toString; +var boolValueOf = Boolean.prototype.valueOf; + +redefine(Boolean.prototype, "toString", function() { return 17; }); +assertEq(JSON.stringify(new Boolean(false)), "false") +delete Boolean.prototype.toString; +assertEq(JSON.stringify(new Boolean(false)), "false"); +delete Object.prototype.toString; +assertEq(JSON.stringify(new Boolean(false)), "false"); +delete Boolean.prototype.valueOf; +assertEq(JSON.stringify(new Boolean(false)), "false"); +delete Object.prototype.valueOf; +assertEq(JSON.stringify(new Boolean(false)), "false"); + + +redefine(Boolean.prototype, "toString", boolToString); +redefine(Boolean.prototype, "valueOf", boolValueOf); +redefine(Object.prototype, "toString", objToString); +redefine(Object.prototype, "valueOf", objValueOf); + +redefine(Number.prototype, "toString", function() { return 42; }); +assertEq(JSON.stringify(new Number(5)), "5"); +redefine(Number.prototype, "valueOf", function() { return 17; }); +assertEq(JSON.stringify(new Number(5)), "17"); +delete Number.prototype.toString; +assertEq(JSON.stringify(new Number(5)), "17"); +delete Number.prototype.valueOf; +assertEq(JSON.stringify(new Number(5)), "null"); // isNaN(Number("[object Number]")) +delete Object.prototype.toString; +try +{ + JSON.stringify(new Number(5)); + throw new Error("didn't throw"); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, + "ToNumber failure, should throw TypeError"); +} +delete Object.prototype.valueOf; +try +{ + JSON.stringify(new Number(5)); + throw new Error("didn't throw"); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, + "ToNumber failure, should throw TypeError"); +} + + +redefine(Number.prototype, "toString", numToString); +redefine(Number.prototype, "valueOf", numValueOf); +redefine(Object.prototype, "toString", objToString); +redefine(Object.prototype, "valueOf", objValueOf); + + +redefine(String.prototype, "valueOf", function() { return 17; }); +assertEq(JSON.stringify(new String(5)), '"5"'); +redefine(String.prototype, "toString", function() { return 42; }); +assertEq(JSON.stringify(new String(5)), '"42"'); +delete String.prototype.toString; +assertEq(JSON.stringify(new String(5)), '"[object String]"'); +delete Object.prototype.toString; +assertEq(JSON.stringify(new String(5)), '"17"'); +delete String.prototype.valueOf; +try +{ + JSON.stringify(new String(5)); + throw new Error("didn't throw"); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, + "ToString failure, should throw TypeError"); +} +delete Object.prototype.valueOf; +try +{ + JSON.stringify(new String(5)); + throw new Error("didn't throw"); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, + "ToString failure, should throw TypeError"); +} + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/JSON/stringify-call-replacer-once.js b/js/src/tests/non262/JSON/stringify-call-replacer-once.js new file mode 100644 index 0000000000..34e549b6e6 --- /dev/null +++ b/js/src/tests/non262/JSON/stringify-call-replacer-once.js @@ -0,0 +1,34 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +var gTestfile = 'stringify-call-replacer-once.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 584909; +var summary = "Call replacer function exactly once per value"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var factor = 1; +function replacer(k, v) +{ + if (k === "") + return v; + + return v * ++factor; +} + +var obj = { a: 1, b: 2, c: 3 }; + +assertEq(JSON.stringify(obj, replacer), '{"a":2,"b":6,"c":12}'); +assertEq(factor, 4); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/stringify-call-toJSON-once.js b/js/src/tests/non262/JSON/stringify-call-toJSON-once.js new file mode 100644 index 0000000000..23917975d9 --- /dev/null +++ b/js/src/tests/non262/JSON/stringify-call-toJSON-once.js @@ -0,0 +1,32 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +var gTestfile = 'stringify-call-toJSON-once.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 584909; +var summary = "Stringification of Boolean/String/Number objects"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var obj = + { + p: { + toJSON: function() + { + return { toJSON: function() { return 17; } }; + } + } + }; + +assertEq(JSON.stringify(obj), '{"p":{}}'); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/stringify-dropping-elements.js b/js/src/tests/non262/JSON/stringify-dropping-elements.js new file mode 100644 index 0000000000..58838e10d1 --- /dev/null +++ b/js/src/tests/non262/JSON/stringify-dropping-elements.js @@ -0,0 +1,20 @@ +assertEq(JSON.stringify({foo: 123}), + '{"foo":123}'); +assertEq(JSON.stringify({foo: 123, bar: function () {}}), + '{"foo":123}'); +assertEq(JSON.stringify({foo: 123, bar: function () {}, baz: 123}), + '{"foo":123,"baz":123}'); + +assertEq(JSON.stringify([123]), + '[123]'); +assertEq(JSON.stringify([123, function () {}]), + '[123,null]'); +assertEq(JSON.stringify([123, function () {}, 456]), + '[123,null,456]'); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/stringify-fastpath.js b/js/src/tests/non262/JSON/stringify-fastpath.js new file mode 100644 index 0000000000..3b1d9e3021 --- /dev/null +++ b/js/src/tests/non262/JSON/stringify-fastpath.js @@ -0,0 +1,212 @@ +// |reftest| skip-if(!xulRuntime.shell) -- not sure why, but invisible errors when running in browser. + +/* + * Any copyright is dedicated to the Public Domain. + * https://creativecommons.org/publicdomain/zero/1.0/ + */ + +if (typeof JSONStringify === "undefined") { + var JSONStringify = SpecialPowers.Cu.getJSTestingFunctions().JSONStringify; +} + +var report = this.console?.error || this.printErr; + +report("BUGNUMBER: 1837410"); + +function compare(obj) { + let slow; + try { slow = JSONStringify(obj, "SlowOnly"); } catch (e) { slow = "" + e; } + let maybeFast; + try { maybeFast = JSONStringify(obj, "Normal"); } catch (e) { maybeFast = "" + e; } + if (slow !== maybeFast) { + report(`Slow:\n${slow}\nFast:\n${maybeFast}`); + return 1; + } + return 0; +} + +function newBigInt(val = 7n) { + let result; + function grabThis() { result = this; } + grabThis.call(BigInt(val)); + return result; +} + +function testBothPaths() { + let failures = 0; + failures += compare([, 3, undefined, ,]); + failures += compare({ a: 1, b: undefined }); + failures += compare({ a: undefined, b: 1 }); + failures += compare({ a: 1, b: Symbol("fnord") }); + + const obj = {}; + obj.first = true; + obj[0] = 'a'; + obj[1] = undefined; + obj[2] = 'b'; + obj.last = true; + failures += compare(obj); + + const cyclic = {}; + cyclic.one = 1; + cyclic.two = { me: cyclic }; + failures += compare(cyclic); + + const sparse = [10, 20, 30]; + sparse[1000] = 40; + failures += compare(sparse); + + const arr = [10, 20, 30]; + arr.other = true; + failures += compare(arr); + + const arr2 = new Array(5); + arr2[1] = 'hello'; + arr2[3] = 'world'; + failures += compare(arr2); + + const big = { p1: 1, p2: 2, p3: 3, p4: 4, p5: 5, p6: 6, p7: 7, p8: 8, p9: 9 }; + failures += compare(big); + + failures += compare(new Number(3)); + failures += compare(new Boolean(true)); + failures += compare(Number.NaN); + failures += compare(undefined); + failures += compare({ x: () => 1 }); + + failures += compare({ x: newBigInt() }); + + const sparse2 = []; + Object.defineProperty(sparse2, "0", { value: 7, enumerable: false }); + failures += compare(sparse2); + + return failures; +} + +function checkFast(value, expectWhySlow) { + let whySlow; + let json; + try { + json = JSONStringify(value, "FastOnly"); + } catch (e) { + const m = e.message.match(/failed mandatory fast path: (\S+)/); + if (!m) { + report("Expected fast path fail, got " + e); + return 1; + } + whySlow = m[1]; + } + + if (expectWhySlow) { + if (!whySlow) { + report("Expected to bail out of fast path but unexpectedly succeeded"); + report((new Error).stack); + report(json); + return 1; + } else if (whySlow != expectWhySlow) { + report(`Expected to bail out of fast path because ${expectWhySlow} but bailed because ${whySlow}`); + return 1; + } + } else { + if (whySlow) { + report("Expected fast path to succeed, bailed because: " + whySlow); + return 1; // Fail + } + } + + return 0; +} + +function testFastPath() { + let failures = 0; + failures += checkFast({}); + failures += checkFast([]); + failures += checkFast({ x: true }); + failures += checkFast([, , 10, ,]); + failures += checkFast({ x: undefined }); + failures += checkFast({ x: Symbol() }); + failures += checkFast({ x: new Set([10,20,30]) }); + + failures += checkFast("primitive", "PRIMITIVE"); + failures += checkFast(true, "PRIMITIVE"); + failures += checkFast(7, "PRIMITIVE"); + + failures += checkFast({ x: new Uint8Array(3) }, "INELIGIBLE_OBJECT"); + failures += checkFast({ x: new Number(3) }, "INELIGIBLE_OBJECT"); + failures += checkFast({ x: new Boolean(true) }, "INELIGIBLE_OBJECT"); + failures += checkFast({ x: newBigInt(3) }, "INELIGIBLE_OBJECT"); + failures += checkFast(Number.NaN, "PRIMITIVE"); + failures += checkFast(undefined, "PRIMITIVE"); + + // Array has enumerated indexed + non-indexed slots. + const nonElements = []; + Object.defineProperty(nonElements, 0, { value: "hi", enumerated: true, configurable: true }); + nonElements.named = 7; + failures += checkFast(nonElements, "INELIGIBLE_OBJECT"); + + nonElements.splice(0); + failures += checkFast(nonElements); + + // Array's prototype has indexed slot and/or inherited element. + const proto = {}; + Object.defineProperty(proto, "0", { value: 1, enumerable: false }); + const holy = [, , 3]; + Object.setPrototypeOf(holy, proto); + failures += checkFast(holy, "INELIGIBLE_OBJECT"); + Object.setPrototypeOf(holy, { 1: true }); + failures += checkFast(holy, "INELIGIBLE_OBJECT"); + + // This is probably redundant with one of the above, but it was + // found by a fuzzer at one point. + const accessorProto = Object.create(Array.prototype); + Object.defineProperty(accessorProto, "0", { + get() { return 2; }, set() { } + }); + const child = []; + Object.setPrototypeOf(child, accessorProto); + child.push(1); + failures += checkFast(child, "INELIGIBLE_OBJECT"); + + failures += checkFast({ get x() { return 1; } }, "NON_DATA_PROPERTY"); + + const self = {}; + self.self = self; + failures += checkFast(self, "DEEP_RECURSION"); + const ouroboros = ['head', 'middle', []]; + let p = ouroboros[2]; + let middle; + for (let i = 0; i < 1000; i++) { + p.push('middle', 'middle'); + p = p[2] = []; + if (i == 10) { + middle = p; + } + } + failures += checkFast(ouroboros, "DEEP_RECURSION"); // Acyclic but deep + p[2] = ouroboros; + failures += checkFast(ouroboros, "DEEP_RECURSION"); // Cyclic and deep + middle[2] = ouroboros; + failures += checkFast(ouroboros, "DEEP_RECURSION"); // Cyclic after 10 recursions + + failures += checkFast({ 0: true, 1: true, 10000: true }, "INELIGIBLE_OBJECT"); + const arr = [1, 2, 3]; + arr[10000] = 4; + failures += checkFast(arr, "INELIGIBLE_OBJECT"); + + failures += checkFast({ x: 12n }, "BIGINT"); + + failures += checkFast({ x: new Date() }, "HAVE_TOJSON"); + failures += checkFast({ toJSON() { return "json"; } }, "HAVE_TOJSON"); + const custom = { toJSON() { return "value"; } }; + failures += checkFast(Object.create(custom), "HAVE_TOJSON"); + + return failures; +} + +let failures = testBothPaths() + testFastPath(); + +if (typeof reportCompare === "function") { + reportCompare(0, failures); +} else { + assertEq(failures, 0); +} diff --git a/js/src/tests/non262/JSON/stringify-gap.js b/js/src/tests/non262/JSON/stringify-gap.js new file mode 100644 index 0000000000..8480b4b3ee --- /dev/null +++ b/js/src/tests/non262/JSON/stringify-gap.js @@ -0,0 +1,61 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +var gTestfile = 'stringify-gap.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 584909; +var summary = + "JSON.stringify(_1, _2, numberGreaterThanOne) produces wrong output"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var LF = "\n"; +var GAP = " "; + +var obj = { a: { b: [1, 2], c: { d: 3, e: 4 }, f: [], g: {}, h: [5], i: { j: 6 } } }; + +var expected = + '{\n' + + ' "a": {\n' + + ' "b": [\n' + + ' 1,\n' + + ' 2\n' + + ' ],\n' + + ' "c": {\n' + + ' "d": 3,\n' + + ' "e": 4\n' + + ' },\n' + + ' "f": [],\n' + + ' "g": {},\n' + + ' "h": [\n' + + ' 5\n' + + ' ],\n' + + ' "i": {\n' + + ' "j": 6\n' + + ' }\n' + + ' }\n' + + '}'; + +assertEq(JSON.stringify(obj, null, 3), expected); +assertEq(JSON.stringify(obj, null, " "), expected); + +obj = [1, 2, 3]; + +String.prototype.toString = function() { return "--"; }; + +assertEq(JSON.stringify(obj, null, new String(" ")), "[\n--1,\n--2,\n--3\n]"); + +Number.prototype.valueOf = function() { return 0; }; + +assertEq(JSON.stringify(obj, null, new Number(3)), "[1,2,3]"); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/JSON/stringify-ignore-noncallable-toJSON.js b/js/src/tests/non262/JSON/stringify-ignore-noncallable-toJSON.js new file mode 100644 index 0000000000..e4ce0ce945 --- /dev/null +++ b/js/src/tests/non262/JSON/stringify-ignore-noncallable-toJSON.js @@ -0,0 +1,28 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +var gTestfile = 'stringify-ignore-noncallable-toJSON.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 584909; +var summary = "If the toJSON property isn't callable, don't try to call it"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var obj = + { + p: { toJSON: null }, + m: { toJSON: {} } + }; + +assertEq(JSON.stringify(obj), '{"p":{"toJSON":null},"m":{"toJSON":{}}}'); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/stringify-large-replacer-array.js b/js/src/tests/non262/JSON/stringify-large-replacer-array.js new file mode 100644 index 0000000000..28180b4bf1 --- /dev/null +++ b/js/src/tests/non262/JSON/stringify-large-replacer-array.js @@ -0,0 +1,26 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +var gTestfile = 'stringify-large-replacer-array.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 816033; +var summary = "JSON.stringify with a large replacer array"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var replacer = []; +for (var i = 0; i < 4096; i++) + replacer.push(i); + +assertEq(JSON.stringify({ "foopy": "FAIL", "4093": 17 }, replacer), '{"4093":17}'); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/stringify-missing-arguments.js b/js/src/tests/non262/JSON/stringify-missing-arguments.js new file mode 100644 index 0000000000..18ca608357 --- /dev/null +++ b/js/src/tests/non262/JSON/stringify-missing-arguments.js @@ -0,0 +1,22 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +var gTestfile = 'stringify-missing-arguments.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 648471; +var summary = "JSON.stringify with no arguments"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +assertEq(JSON.stringify(), undefined); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/JSON/stringify-nonarray-noncallable-replacer.js b/js/src/tests/non262/JSON/stringify-nonarray-noncallable-replacer.js new file mode 100644 index 0000000000..440fbc0aae --- /dev/null +++ b/js/src/tests/non262/JSON/stringify-nonarray-noncallable-replacer.js @@ -0,0 +1,41 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +var gTestfile = 'stringify-nonarray-noncallable-replacer.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 653782; +var summary = + "Treat non-array, non-callable replacers as if none had been specified"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var obj = { p: 2 }; +var str = '{"p":2}'; + +assertEq(JSON.stringify(obj), str); +assertEq(JSON.stringify(obj, ["p"]), str); +assertEq(JSON.stringify(obj, null), str); +assertEq(JSON.stringify(obj, undefined), str); +assertEq(JSON.stringify(obj, 2), str); +assertEq(JSON.stringify(obj, Math.PI), str); +assertEq(JSON.stringify(obj, NaN), str); +assertEq(JSON.stringify(obj, true), str); +assertEq(JSON.stringify(obj, false), str); +assertEq(JSON.stringify(obj, Infinity), str); +assertEq(JSON.stringify(obj, "foopy"), str); +assertEq(JSON.stringify(obj, {}), str); +assertEq(JSON.stringify(obj, /abcd/), str); +assertEq(JSON.stringify(obj, new Boolean(true)), str); +assertEq(JSON.stringify(obj, new Number(42)), str); +assertEq(JSON.stringify(obj, new String("aequorin")), str); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/stringify-primitives.js b/js/src/tests/non262/JSON/stringify-primitives.js new file mode 100644 index 0000000000..3f48638b8b --- /dev/null +++ b/js/src/tests/non262/JSON/stringify-primitives.js @@ -0,0 +1,39 @@ +// sanity +var x = JSON.stringify({}); +assertEq(x, "{}"); + +// booleans and null +x = JSON.stringify(true); +assertEq(x, "true"); + +x = JSON.stringify(false); +assertEq(x, "false"); + +x = JSON.stringify(new Boolean(false)); +assertEq(x, "false"); + +x = JSON.stringify(null); +assertEq(x, "null"); + +x = JSON.stringify(1234); +assertEq(x, "1234"); + +x = JSON.stringify(new Number(1234)); +assertEq(x, "1234"); + +x = JSON.stringify("asdf"); +assertEq(x, '"asdf"'); + +x = JSON.stringify(new String("asdf")); +assertEq(x, '"asdf"'); + +assertEq(JSON.stringify(undefined), undefined); +assertEq(JSON.stringify(function(){}), undefined); +assertEq(JSON.stringify(JSON.stringify), undefined); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/stringify-replacer-array-boxed-elements.js b/js/src/tests/non262/JSON/stringify-replacer-array-boxed-elements.js new file mode 100644 index 0000000000..561f7009c7 --- /dev/null +++ b/js/src/tests/non262/JSON/stringify-replacer-array-boxed-elements.js @@ -0,0 +1,60 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +var gTestfile = 'stringify-replacer-array-boxed-elements.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 648471; +var summary = "Boxed-string/number objects in replacer arrays"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var S = new String(3); +var N = new Number(4); + +assertEq(JSON.stringify({ 3: 3, 4: 4 }, [S]), + '{"3":3}'); +assertEq(JSON.stringify({ 3: 3, 4: 4 }, [N]), + '{"4":4}'); + +Number.prototype.toString = function() { return 3; }; +assertEq(JSON.stringify({ 3: 3, 4: 4 }, [N]), + '{"3":3}'); + +String.prototype.toString = function() { return 4; }; +assertEq(JSON.stringify({ 3: 3, 4: 4 }, [S]), + '{"4":4}'); + +Number.prototype.toString = function() { return new String(42); }; +assertEq(JSON.stringify({ 3: 3, 4: 4 }, [N]), + '{"4":4}'); + +String.prototype.toString = function() { return new Number(17); }; +assertEq(JSON.stringify({ 3: 3, 4: 4 }, [S]), + '{"3":3}'); + +Number.prototype.toString = null; +assertEq(JSON.stringify({ 3: 3, 4: 4 }, [N]), + '{"4":4}'); + +String.prototype.toString = null; +assertEq(JSON.stringify({ 3: 3, 4: 4 }, [S]), + '{"3":3}'); + +Number.prototype.valueOf = function() { return 17; }; +assertEq(JSON.stringify({ 4: 4, 17: 17 }, [N]), + '{"17":17}'); + +String.prototype.valueOf = function() { return 42; }; +assertEq(JSON.stringify({ 3: 3, 42: 42 }, [S]), + '{"42":42}'); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/stringify-replacer-array-duplicated-element.js b/js/src/tests/non262/JSON/stringify-replacer-array-duplicated-element.js new file mode 100644 index 0000000000..69192e6cae --- /dev/null +++ b/js/src/tests/non262/JSON/stringify-replacer-array-duplicated-element.js @@ -0,0 +1,69 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +var gTestfile = 'stringify-replacer-array-hijinks.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 648471; +var summary = + "Better/more correct handling for replacer arrays with getter array index " + + "properties"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var bigOdd = Math.pow(2, 50) + 1; + +function two() +{ + return Math.random() < 0.5 ? 2 : "2"; +} + +assertEq(JSON.stringify({ 1: 1 }, [1, 1]), '{"1":1}'); + +assertEq(JSON.stringify({ 1: 1 }, [1, "1"]), '{"1":1}'); + +assertEq(JSON.stringify({ 1: 1 }, [1, bigOdd % two()]), '{"1":1}'); + +assertEq(JSON.stringify({ 1: 1 }, ["1", 1]), '{"1":1}'); + +assertEq(JSON.stringify({ 1: 1 }, ["1", "1"]), '{"1":1}'); + +assertEq(JSON.stringify({ 1: 1 }, ["1", bigOdd % two()]), '{"1":1}'); + +assertEq(JSON.stringify({ 1: 1 }, [bigOdd % two(), 1]), '{"1":1}'); + +assertEq(JSON.stringify({ 1: 1 }, [bigOdd % two(), "1"]), '{"1":1}'); + +assertEq(JSON.stringify({ 1: 1 }, [bigOdd % two(), bigOdd % two()]), '{"1":1}'); + + +assertEq(JSON.stringify({ 1: 1 }, [1, new String(1)]), '{"1":1}'); + +assertEq(JSON.stringify({ 1: 1 }, [1, new Number(1)]), '{"1":1}'); + +assertEq(JSON.stringify({ 1: 1 }, ["1", new Number(1)]), '{"1":1}'); + +assertEq(JSON.stringify({ 1: 1 }, ["1", new String(1)]), '{"1":1}'); + +assertEq(JSON.stringify({ 1: 1 }, [bigOdd % two(), new Number(1)]), '{"1":1}'); + +assertEq(JSON.stringify({ 1: 1 }, [bigOdd % two(), new String(1)]), '{"1":1}'); + + +assertEq(JSON.stringify({ 1: 1 }, [new String(1), new String(1)]), '{"1":1}'); + +assertEq(JSON.stringify({ 1: 1 }, [new String(1), new Number(1)]), '{"1":1}'); + +assertEq(JSON.stringify({ 1: 1 }, [new Number(1), new String(1)]), '{"1":1}'); + +assertEq(JSON.stringify({ 1: 1 }, [new Number(1), new Number(1)]), '{"1":1}'); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/stringify-replacer-array-edgecase-jsid-elements.js b/js/src/tests/non262/JSON/stringify-replacer-array-edgecase-jsid-elements.js new file mode 100644 index 0000000000..e7be4c6e11 --- /dev/null +++ b/js/src/tests/non262/JSON/stringify-replacer-array-edgecase-jsid-elements.js @@ -0,0 +1,77 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +var gTestfile = 'stringify-replacer-array-edgecase-jsid-elements.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 648471; +var summary = + "Better/more correct handling for replacer arrays with getter array index " + + "properties"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +/* JSID_INT_MIN/MAX copied from jsapi.h. */ + +var obj = + { + /* [JSID_INT_MIN - 1, JSID_INT_MIN + 1] */ + "-1073741825": -1073741825, + "-1073741824": -1073741824, + "-1073741823": -1073741823, + + "-2.5": -2.5, + "-1": -1, + + 0: 0, + + 1: 1, + 2.5: 2.5, + + /* [JSID_INT_MAX - 1, JSID_INT_MAX + 1] */ + 1073741822: 1073741822, + 1073741823: 1073741823, + 1073741824: 1073741824, + }; + +for (var s in obj) +{ + var n = obj[s]; + assertEq(+s, n); + assertEq(JSON.stringify(obj, [n]), + '{"' + s + '":' + n + '}', + "Failed to stringify numeric property " + n + "correctly"); + assertEq(JSON.stringify(obj, [s]), + '{"' + s + '":' + n + '}', + "Failed to stringify string property " + n + "correctly"); + assertEq(JSON.stringify(obj, [s, ]), + '{"' + s + '":' + n + '}', + "Failed to stringify string then number properties ('" + s + "', " + n + ") correctly"); + assertEq(JSON.stringify(obj, [n, s]), + '{"' + s + '":' + n + '}', + "Failed to stringify number then string properties (" + n + ", '" + s + "') correctly"); +} + +// -0 is tricky, because ToString(-0) === "0", so test it specially. +assertEq(JSON.stringify({ "-0": 17, 0: 42 }, [-0]), + '{"0":42}', + "Failed to stringify numeric property -0 correctly"); +assertEq(JSON.stringify({ "-0": 17, 0: 42 }, ["-0"]), + '{"-0":17}', + "Failed to stringify string property -0 correctly"); +assertEq(JSON.stringify({ "-0": 17, 0: 42 }, ["-0", -0]), + '{"-0":17,"0":42}', + "Failed to stringify string then number properties ('-0', -0) correctly"); +assertEq(JSON.stringify({ "-0": 17, 0: 42 }, [-0, "-0"]), + '{"0":42,"-0":17}', + "Failed to stringify number then string properties (-0, '-0) correctly"); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/stringify-replacer-array-hijinks.js b/js/src/tests/non262/JSON/stringify-replacer-array-hijinks.js new file mode 100644 index 0000000000..60c949a5f1 --- /dev/null +++ b/js/src/tests/non262/JSON/stringify-replacer-array-hijinks.js @@ -0,0 +1,59 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +var gTestfile = 'stringify-replacer-array-hijinks.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 648471; +var summary = + "Better/more correct handling for replacer arrays with getter array index " + + "properties"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var replacer = [0, 1, 2, 3]; +Object.prototype[3] = 3; +Object.defineProperty(replacer, 1, { + get: function() + { + Object.defineProperty(replacer, 4, { value: 4 }); + delete replacer[2]; + delete replacer[3]; + replacer[5] = 5; + return 1; + } +}); + +var s = + JSON.stringify({0: { 1: { 3: { 4: { 5: { 2: "omitted" } } } } } }, replacer); + +// The replacer array's length is as seen on first query, so property names are +// accumulated for indexes i ∈ {0, 1, 2, 3}, but index 1 deletes 2 and 3, so 2 +// isn't seen but 3 is seen as Object.prototype[3]. +assertEq('{"0":{"1":{"3":{"3":3}},"3":3},"3":3}', s); + + +var replacer = [0, 1, 2, 3]; +Object.defineProperty(replacer, 0, { + get: function() + { + replacer.length = 0; + return {}; + } +}); + +// The replacer.length truncation means only properties on the prototype chain +// shine through, but it doesn't affect the original bounds of the iteration +// used to determine property names which will be included in the final string. +assertEq(JSON.stringify({ 0: 0, 1: 1, 2: 2, 3: 3 }, replacer), + '{"3":3}'); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/stringify-replacer-array-skipped-element.js b/js/src/tests/non262/JSON/stringify-replacer-array-skipped-element.js new file mode 100644 index 0000000000..6297c3a5bf --- /dev/null +++ b/js/src/tests/non262/JSON/stringify-replacer-array-skipped-element.js @@ -0,0 +1,62 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +var gTestfile = 'stringify-replacer-array-skipped-element.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 648471; +var summary = + "Better/more correct handling for replacer arrays with getter array index " + + "properties"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +assertEq(JSON.stringify({ 3: 3, 4: 4 }, + ["3", { toString: function() { return "4" } }]), + '{"3":3}'); + +assertEq(JSON.stringify({ 3: 3, true: 4 }, ["3", true]), + '{"3":3}'); + +assertEq(JSON.stringify({ 3: 3, true: 4 }, ["3", "true", true]), + '{"3":3,"true":4}'); + +assertEq(JSON.stringify({ 3: 3, true: 4 }, ["3", true, "true"]), + '{"3":3,"true":4}'); + +assertEq(JSON.stringify({ 3: 3, false: 4 }, ["3", false]), + '{"3":3}'); + +assertEq(JSON.stringify({ 3: 3, false: 4 }, ["3", "false", false]), + '{"3":3,"false":4}'); + +assertEq(JSON.stringify({ 3: 3, false: 4 }, ["3", false, "false"]), + '{"3":3,"false":4}'); + +assertEq(JSON.stringify({ 3: 3, undefined: 4 }, ["3", undefined]), + '{"3":3}'); + +assertEq(JSON.stringify({ 3: 3, undefined: 4 }, ["3", "undefined", undefined]), + '{"3":3,"undefined":4}'); + +assertEq(JSON.stringify({ 3: 3, undefined: 4 }, ["3", undefined, "undefined"]), + '{"3":3,"undefined":4}'); + +assertEq(JSON.stringify({ 3: 3, null: 4 }, ["3", null]), + '{"3":3}'); + +assertEq(JSON.stringify({ 3: 3, null: 4 }, ["3", "null", null]), + '{"3":3,"null":4}'); + +assertEq(JSON.stringify({ 3: 3, null: 4 }, ["3", null, "null"]), + '{"3":3,"null":4}'); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/stringify-replacer-array-trailing-holes.js b/js/src/tests/non262/JSON/stringify-replacer-array-trailing-holes.js new file mode 100644 index 0000000000..6eb09855fa --- /dev/null +++ b/js/src/tests/non262/JSON/stringify-replacer-array-trailing-holes.js @@ -0,0 +1,49 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +var gTestfile = "stringify-replacer-array-trailing-holes.js"; +//----------------------------------------------------------------------------- +var BUGNUMBER = 1217069; +var summary = + "Better/more correct handling for replacer arrays with trailing holes " + + "through which inherited elements might appear"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var obj = { 0: "hi", 1: "n-nao", 2: "run away!", 3: "bye" }; + +var s; + +var replacer = [0, /* 1 */, /* 2 */, /* 3 */, ]; + +assertEq(JSON.stringify(obj, replacer), + '{"0":"hi"}'); + +var nobj = new Number(0); +nobj.toString = () => { replacer[1] = 1; return 0; }; +replacer[0] = nobj; + +assertEq(JSON.stringify(obj, replacer), + '{"0":"hi","1":"n-nao"}'); + +delete replacer[1]; +replacer[0] = 0; + +Object.prototype[0] = 0; +Object.prototype[1] = 1; +Object.prototype[2] = 2; +Object.prototype[3] = 3; + +assertEq(JSON.stringify(obj, replacer), + '{"0":"hi","1":"n-nao","2":"run away!","3":"bye"}'); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/stringify-replacer-with-array-indexes.js b/js/src/tests/non262/JSON/stringify-replacer-with-array-indexes.js new file mode 100644 index 0000000000..0b3f6896e5 --- /dev/null +++ b/js/src/tests/non262/JSON/stringify-replacer-with-array-indexes.js @@ -0,0 +1,56 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +var gTestfile = 'stringify-replacer-with-array-indexes.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 584909; +var summary = + "Call the replacer function for array elements with stringified indexes"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var arr = [0, 1, 2, 3, 4]; + +var seenTopmost = false; +var index = 0; +function replacer() +{ + assertEq(arguments.length, 2); + + var key = arguments[0], value = arguments[1]; + + // Topmost array: ignore replacer call. + if (key === "") + { + assertEq(seenTopmost, false); + seenTopmost = true; + return value; + } + + assertEq(seenTopmost, true); + + assertEq(typeof key, "string"); + assertEq(key === index, false); + assertEq(key === index + "", true); + + assertEq(value, index); + + index++; + + assertEq(this, arr); + + return value; +} + +assertEq(JSON.stringify(arr, replacer), '[0,1,2,3,4]'); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/stringify-replacer.js b/js/src/tests/non262/JSON/stringify-replacer.js new file mode 100644 index 0000000000..37497fd348 --- /dev/null +++ b/js/src/tests/non262/JSON/stringify-replacer.js @@ -0,0 +1,155 @@ +/** + * These return* functions are used by the + * replacer tests taken from bug 512447 + */ +function returnObjectFor1(k, v) +{ + if (k == "1") + return {}; + return v; +} +function returnArrayFor1(k, v) +{ + if (k == "1") + return []; + return v; +} +function returnNullFor1(k, v) +{ + if (k == "1") + return null; + return v; +} +function returnStringForUndefined(k, v) +{ + if (v === undefined) + return "undefined value"; + return v; +} +var cycleObject = {}; cycleObject.cycle = cycleObject; +function returnCycleObjectFor1(k, v) +{ + if (k == "1") + return cycleObject; + return v; +} +var array = [0, 1, 2]; array[3] = array; +function returnCycleArrayFor1(k, v) +{ + if (k == "1") + return array; + return v; +} + +// BEGIN TEST +var x; + +x = JSON.stringify({ key: 2 }, + function(k,v) { return k ? undefined : v; }); +assertEq(x, "{}"); + +x = JSON.stringify(["hmm", "hmm"], + function(k,v) { return k !== "" ? undefined : v; }); +assertEq(x, "[null,null]"); + +var foo = ["hmm"]; +function censor(k, v) +{ + if (v !== foo) + return "XXX"; + return v; +} +x = JSON.stringify(foo, censor); +assertEq(x, '["XXX"]'); + +foo = ["bar", ["baz"], "qux"]; +x = JSON.stringify(foo, censor); +assertEq(x, '["XXX","XXX","XXX"]'); + +function censor2(k, v) +{ + if (typeof(v) == "string") + return "XXX"; + return v; +} + +foo = ["bar", ["baz"], "qux"]; +x = JSON.stringify(foo, censor2); +assertEq(x, '["XXX",["XXX"],"XXX"]'); + +foo = { bar: 42, qux: 42, quux: 42 }; +x = JSON.stringify(foo, ["bar"]); +assertEq(x, '{"bar":42}'); + +foo = {bar: {bar: 42, schmoo:[]}, qux: 42, quux: 42}; +x = JSON.stringify(foo, ["bar", "schmoo"]); +assertEq(x, '{"bar":{"bar":42,"schmoo":[]}}'); + +x = JSON.stringify(foo, null, ""); +assertEq(x, '{"bar":{"bar":42,"schmoo":[]},"qux":42,"quux":42}'); + +x = JSON.stringify(foo, null, " "); +assertEq(x, '{\n "bar": {\n "bar": 42,\n "schmoo": []\n },\n "qux": 42,\n "quux": 42\n}'); + +foo = {bar:{bar:{}}} +x = JSON.stringify(foo, null, " "); +assertEq(x, '{\n "bar": {\n "bar": {}\n }\n}'); + +x = JSON.stringify({ x: 1, arr: [1] }, + function (k,v) { return typeof v === 'number' ? 3 : v; }); +assertEq(x, '{"x":3,"arr":[3]}'); + +foo = ['e']; +x = JSON.stringify(foo, null, '\t'); +assertEq(x, '[\n\t"e"\n]'); + +foo = {0:0, 1:1, 2:2, 3:undefined}; +x = JSON.stringify(foo, returnObjectFor1); +assertEq(x, '{"0":0,"1":{},"2":2}'); + +x = JSON.stringify(foo, returnArrayFor1); +assertEq(x, '{"0":0,"1":[],"2":2}'); + +x = JSON.stringify(foo, returnNullFor1); +assertEq(x, '{"0":0,"1":null,"2":2}'); + +x = JSON.stringify(foo, returnStringForUndefined); +assertEq(x, '{"0":0,"1":1,"2":2,"3":"undefined value"}'); + +try +{ + JSON.stringify(foo, returnCycleObjectFor1); + throw new Error("no error thrown"); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, "no TypeError thrown: " + e); +} + +try +{ + JSON.stringify(foo, returnCycleArrayFor1); + throw new Error("no error thrown"); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, "no TypeError thrown: " + e); +} + +foo = [0, 1, 2, undefined]; +try +{ + JSON.stringify(foo, returnCycleObjectFor1); + throw new Error("no error thrown"); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, "no TypeError thrown: " + e); +} + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/stringify-special-escapes.js b/js/src/tests/non262/JSON/stringify-special-escapes.js new file mode 100644 index 0000000000..c8a2e83815 --- /dev/null +++ b/js/src/tests/non262/JSON/stringify-special-escapes.js @@ -0,0 +1,277 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +var gTestfile = 'stringify-special-escapes.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 512266; +var summary = + "JSON.stringify of \\b\\f\\n\\r\\t should use one-character escapes, not hex"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +assertEq(JSON.stringify("\u0000"), '"\\u0000"'); +assertEq(JSON.stringify("\u0001"), '"\\u0001"'); +assertEq(JSON.stringify("\u0002"), '"\\u0002"'); +assertEq(JSON.stringify("\u0003"), '"\\u0003"'); +assertEq(JSON.stringify("\u0004"), '"\\u0004"'); +assertEq(JSON.stringify("\u0005"), '"\\u0005"'); +assertEq(JSON.stringify("\u0006"), '"\\u0006"'); +assertEq(JSON.stringify("\u0007"), '"\\u0007"'); +assertEq(JSON.stringify("\u0008"), '"\\b"'); +assertEq(JSON.stringify("\u0009"), '"\\t"'); +assertEq(JSON.stringify("\u000A"), '"\\n"'); +assertEq(JSON.stringify("\u000B"), '"\\u000b"'); +assertEq(JSON.stringify("\u000C"), '"\\f"'); +assertEq(JSON.stringify("\u000D"), '"\\r"'); +assertEq(JSON.stringify("\u000E"), '"\\u000e"'); +assertEq(JSON.stringify("\u000F"), '"\\u000f"'); +assertEq(JSON.stringify("\u0010"), '"\\u0010"'); +assertEq(JSON.stringify("\u0011"), '"\\u0011"'); +assertEq(JSON.stringify("\u0012"), '"\\u0012"'); +assertEq(JSON.stringify("\u0013"), '"\\u0013"'); +assertEq(JSON.stringify("\u0014"), '"\\u0014"'); +assertEq(JSON.stringify("\u0015"), '"\\u0015"'); +assertEq(JSON.stringify("\u0016"), '"\\u0016"'); +assertEq(JSON.stringify("\u0017"), '"\\u0017"'); +assertEq(JSON.stringify("\u0018"), '"\\u0018"'); +assertEq(JSON.stringify("\u0019"), '"\\u0019"'); +assertEq(JSON.stringify("\u001A"), '"\\u001a"'); +assertEq(JSON.stringify("\u001B"), '"\\u001b"'); +assertEq(JSON.stringify("\u001C"), '"\\u001c"'); +assertEq(JSON.stringify("\u001D"), '"\\u001d"'); +assertEq(JSON.stringify("\u001E"), '"\\u001e"'); +assertEq(JSON.stringify("\u001F"), '"\\u001f"'); +assertEq(JSON.stringify("\u0020"), '" "'); + +assertEq(JSON.stringify("\\u0000"), '"\\\\u0000"'); +assertEq(JSON.stringify("\\u0001"), '"\\\\u0001"'); +assertEq(JSON.stringify("\\u0002"), '"\\\\u0002"'); +assertEq(JSON.stringify("\\u0003"), '"\\\\u0003"'); +assertEq(JSON.stringify("\\u0004"), '"\\\\u0004"'); +assertEq(JSON.stringify("\\u0005"), '"\\\\u0005"'); +assertEq(JSON.stringify("\\u0006"), '"\\\\u0006"'); +assertEq(JSON.stringify("\\u0007"), '"\\\\u0007"'); +assertEq(JSON.stringify("\\u0008"), '"\\\\u0008"'); +assertEq(JSON.stringify("\\u0009"), '"\\\\u0009"'); +assertEq(JSON.stringify("\\u000A"), '"\\\\u000A"'); +assertEq(JSON.stringify("\\u000B"), '"\\\\u000B"'); +assertEq(JSON.stringify("\\u000C"), '"\\\\u000C"'); +assertEq(JSON.stringify("\\u000D"), '"\\\\u000D"'); +assertEq(JSON.stringify("\\u000E"), '"\\\\u000E"'); +assertEq(JSON.stringify("\\u000F"), '"\\\\u000F"'); +assertEq(JSON.stringify("\\u0010"), '"\\\\u0010"'); +assertEq(JSON.stringify("\\u0011"), '"\\\\u0011"'); +assertEq(JSON.stringify("\\u0012"), '"\\\\u0012"'); +assertEq(JSON.stringify("\\u0013"), '"\\\\u0013"'); +assertEq(JSON.stringify("\\u0014"), '"\\\\u0014"'); +assertEq(JSON.stringify("\\u0015"), '"\\\\u0015"'); +assertEq(JSON.stringify("\\u0016"), '"\\\\u0016"'); +assertEq(JSON.stringify("\\u0017"), '"\\\\u0017"'); +assertEq(JSON.stringify("\\u0018"), '"\\\\u0018"'); +assertEq(JSON.stringify("\\u0019"), '"\\\\u0019"'); +assertEq(JSON.stringify("\\u001A"), '"\\\\u001A"'); +assertEq(JSON.stringify("\\u001B"), '"\\\\u001B"'); +assertEq(JSON.stringify("\\u001C"), '"\\\\u001C"'); +assertEq(JSON.stringify("\\u001D"), '"\\\\u001D"'); +assertEq(JSON.stringify("\\u001E"), '"\\\\u001E"'); +assertEq(JSON.stringify("\\u001F"), '"\\\\u001F"'); +assertEq(JSON.stringify("\\u0020"), '"\\\\u0020"'); + + +assertEq(JSON.stringify("a\u0000"), '"a\\u0000"'); +assertEq(JSON.stringify("a\u0001"), '"a\\u0001"'); +assertEq(JSON.stringify("a\u0002"), '"a\\u0002"'); +assertEq(JSON.stringify("a\u0003"), '"a\\u0003"'); +assertEq(JSON.stringify("a\u0004"), '"a\\u0004"'); +assertEq(JSON.stringify("a\u0005"), '"a\\u0005"'); +assertEq(JSON.stringify("a\u0006"), '"a\\u0006"'); +assertEq(JSON.stringify("a\u0007"), '"a\\u0007"'); +assertEq(JSON.stringify("a\u0008"), '"a\\b"'); +assertEq(JSON.stringify("a\u0009"), '"a\\t"'); +assertEq(JSON.stringify("a\u000A"), '"a\\n"'); +assertEq(JSON.stringify("a\u000B"), '"a\\u000b"'); +assertEq(JSON.stringify("a\u000C"), '"a\\f"'); +assertEq(JSON.stringify("a\u000D"), '"a\\r"'); +assertEq(JSON.stringify("a\u000E"), '"a\\u000e"'); +assertEq(JSON.stringify("a\u000F"), '"a\\u000f"'); +assertEq(JSON.stringify("a\u0010"), '"a\\u0010"'); +assertEq(JSON.stringify("a\u0011"), '"a\\u0011"'); +assertEq(JSON.stringify("a\u0012"), '"a\\u0012"'); +assertEq(JSON.stringify("a\u0013"), '"a\\u0013"'); +assertEq(JSON.stringify("a\u0014"), '"a\\u0014"'); +assertEq(JSON.stringify("a\u0015"), '"a\\u0015"'); +assertEq(JSON.stringify("a\u0016"), '"a\\u0016"'); +assertEq(JSON.stringify("a\u0017"), '"a\\u0017"'); +assertEq(JSON.stringify("a\u0018"), '"a\\u0018"'); +assertEq(JSON.stringify("a\u0019"), '"a\\u0019"'); +assertEq(JSON.stringify("a\u001A"), '"a\\u001a"'); +assertEq(JSON.stringify("a\u001B"), '"a\\u001b"'); +assertEq(JSON.stringify("a\u001C"), '"a\\u001c"'); +assertEq(JSON.stringify("a\u001D"), '"a\\u001d"'); +assertEq(JSON.stringify("a\u001E"), '"a\\u001e"'); +assertEq(JSON.stringify("a\u001F"), '"a\\u001f"'); +assertEq(JSON.stringify("a\u0020"), '"a "'); + +assertEq(JSON.stringify("a\\u0000"), '"a\\\\u0000"'); +assertEq(JSON.stringify("a\\u0001"), '"a\\\\u0001"'); +assertEq(JSON.stringify("a\\u0002"), '"a\\\\u0002"'); +assertEq(JSON.stringify("a\\u0003"), '"a\\\\u0003"'); +assertEq(JSON.stringify("a\\u0004"), '"a\\\\u0004"'); +assertEq(JSON.stringify("a\\u0005"), '"a\\\\u0005"'); +assertEq(JSON.stringify("a\\u0006"), '"a\\\\u0006"'); +assertEq(JSON.stringify("a\\u0007"), '"a\\\\u0007"'); +assertEq(JSON.stringify("a\\u0008"), '"a\\\\u0008"'); +assertEq(JSON.stringify("a\\u0009"), '"a\\\\u0009"'); +assertEq(JSON.stringify("a\\u000A"), '"a\\\\u000A"'); +assertEq(JSON.stringify("a\\u000B"), '"a\\\\u000B"'); +assertEq(JSON.stringify("a\\u000C"), '"a\\\\u000C"'); +assertEq(JSON.stringify("a\\u000D"), '"a\\\\u000D"'); +assertEq(JSON.stringify("a\\u000E"), '"a\\\\u000E"'); +assertEq(JSON.stringify("a\\u000F"), '"a\\\\u000F"'); +assertEq(JSON.stringify("a\\u0010"), '"a\\\\u0010"'); +assertEq(JSON.stringify("a\\u0011"), '"a\\\\u0011"'); +assertEq(JSON.stringify("a\\u0012"), '"a\\\\u0012"'); +assertEq(JSON.stringify("a\\u0013"), '"a\\\\u0013"'); +assertEq(JSON.stringify("a\\u0014"), '"a\\\\u0014"'); +assertEq(JSON.stringify("a\\u0015"), '"a\\\\u0015"'); +assertEq(JSON.stringify("a\\u0016"), '"a\\\\u0016"'); +assertEq(JSON.stringify("a\\u0017"), '"a\\\\u0017"'); +assertEq(JSON.stringify("a\\u0018"), '"a\\\\u0018"'); +assertEq(JSON.stringify("a\\u0019"), '"a\\\\u0019"'); +assertEq(JSON.stringify("a\\u001A"), '"a\\\\u001A"'); +assertEq(JSON.stringify("a\\u001B"), '"a\\\\u001B"'); +assertEq(JSON.stringify("a\\u001C"), '"a\\\\u001C"'); +assertEq(JSON.stringify("a\\u001D"), '"a\\\\u001D"'); +assertEq(JSON.stringify("a\\u001E"), '"a\\\\u001E"'); +assertEq(JSON.stringify("a\\u001F"), '"a\\\\u001F"'); +assertEq(JSON.stringify("a\\u0020"), '"a\\\\u0020"'); + + +assertEq(JSON.stringify("\u0000Q"), '"\\u0000Q"'); +assertEq(JSON.stringify("\u0001Q"), '"\\u0001Q"'); +assertEq(JSON.stringify("\u0002Q"), '"\\u0002Q"'); +assertEq(JSON.stringify("\u0003Q"), '"\\u0003Q"'); +assertEq(JSON.stringify("\u0004Q"), '"\\u0004Q"'); +assertEq(JSON.stringify("\u0005Q"), '"\\u0005Q"'); +assertEq(JSON.stringify("\u0006Q"), '"\\u0006Q"'); +assertEq(JSON.stringify("\u0007Q"), '"\\u0007Q"'); +assertEq(JSON.stringify("\u0008Q"), '"\\bQ"'); +assertEq(JSON.stringify("\u0009Q"), '"\\tQ"'); +assertEq(JSON.stringify("\u000AQ"), '"\\nQ"'); +assertEq(JSON.stringify("\u000BQ"), '"\\u000bQ"'); +assertEq(JSON.stringify("\u000CQ"), '"\\fQ"'); +assertEq(JSON.stringify("\u000DQ"), '"\\rQ"'); +assertEq(JSON.stringify("\u000EQ"), '"\\u000eQ"'); +assertEq(JSON.stringify("\u000FQ"), '"\\u000fQ"'); +assertEq(JSON.stringify("\u0010Q"), '"\\u0010Q"'); +assertEq(JSON.stringify("\u0011Q"), '"\\u0011Q"'); +assertEq(JSON.stringify("\u0012Q"), '"\\u0012Q"'); +assertEq(JSON.stringify("\u0013Q"), '"\\u0013Q"'); +assertEq(JSON.stringify("\u0014Q"), '"\\u0014Q"'); +assertEq(JSON.stringify("\u0015Q"), '"\\u0015Q"'); +assertEq(JSON.stringify("\u0016Q"), '"\\u0016Q"'); +assertEq(JSON.stringify("\u0017Q"), '"\\u0017Q"'); +assertEq(JSON.stringify("\u0018Q"), '"\\u0018Q"'); +assertEq(JSON.stringify("\u0019Q"), '"\\u0019Q"'); +assertEq(JSON.stringify("\u001AQ"), '"\\u001aQ"'); +assertEq(JSON.stringify("\u001BQ"), '"\\u001bQ"'); +assertEq(JSON.stringify("\u001CQ"), '"\\u001cQ"'); +assertEq(JSON.stringify("\u001DQ"), '"\\u001dQ"'); +assertEq(JSON.stringify("\u001EQ"), '"\\u001eQ"'); +assertEq(JSON.stringify("\u001FQ"), '"\\u001fQ"'); +assertEq(JSON.stringify("\u0020Q"), '" Q"'); + +assertEq(JSON.stringify("\\u0000Q"), '"\\\\u0000Q"'); +assertEq(JSON.stringify("\\u0001Q"), '"\\\\u0001Q"'); +assertEq(JSON.stringify("\\u0002Q"), '"\\\\u0002Q"'); +assertEq(JSON.stringify("\\u0003Q"), '"\\\\u0003Q"'); +assertEq(JSON.stringify("\\u0004Q"), '"\\\\u0004Q"'); +assertEq(JSON.stringify("\\u0005Q"), '"\\\\u0005Q"'); +assertEq(JSON.stringify("\\u0006Q"), '"\\\\u0006Q"'); +assertEq(JSON.stringify("\\u0007Q"), '"\\\\u0007Q"'); +assertEq(JSON.stringify("\\u0008Q"), '"\\\\u0008Q"'); +assertEq(JSON.stringify("\\u0009Q"), '"\\\\u0009Q"'); +assertEq(JSON.stringify("\\u000AQ"), '"\\\\u000AQ"'); +assertEq(JSON.stringify("\\u000BQ"), '"\\\\u000BQ"'); +assertEq(JSON.stringify("\\u000CQ"), '"\\\\u000CQ"'); +assertEq(JSON.stringify("\\u000DQ"), '"\\\\u000DQ"'); +assertEq(JSON.stringify("\\u000EQ"), '"\\\\u000EQ"'); +assertEq(JSON.stringify("\\u000FQ"), '"\\\\u000FQ"'); +assertEq(JSON.stringify("\\u0010Q"), '"\\\\u0010Q"'); +assertEq(JSON.stringify("\\u0011Q"), '"\\\\u0011Q"'); +assertEq(JSON.stringify("\\u0012Q"), '"\\\\u0012Q"'); +assertEq(JSON.stringify("\\u0013Q"), '"\\\\u0013Q"'); +assertEq(JSON.stringify("\\u0014Q"), '"\\\\u0014Q"'); +assertEq(JSON.stringify("\\u0015Q"), '"\\\\u0015Q"'); +assertEq(JSON.stringify("\\u0016Q"), '"\\\\u0016Q"'); +assertEq(JSON.stringify("\\u0017Q"), '"\\\\u0017Q"'); +assertEq(JSON.stringify("\\u0018Q"), '"\\\\u0018Q"'); +assertEq(JSON.stringify("\\u0019Q"), '"\\\\u0019Q"'); +assertEq(JSON.stringify("\\u001AQ"), '"\\\\u001AQ"'); +assertEq(JSON.stringify("\\u001BQ"), '"\\\\u001BQ"'); +assertEq(JSON.stringify("\\u001CQ"), '"\\\\u001CQ"'); +assertEq(JSON.stringify("\\u001DQ"), '"\\\\u001DQ"'); +assertEq(JSON.stringify("\\u001EQ"), '"\\\\u001EQ"'); +assertEq(JSON.stringify("\\u001FQ"), '"\\\\u001FQ"'); +assertEq(JSON.stringify("\\u0020Q"), '"\\\\u0020Q"'); + +// https://tc39.github.io/proposal-well-formed-stringify/ + +assertEq(JSON.stringify("\ud7ff"), '"\ud7ff"'); +assertEq(JSON.stringify("\ud800"), '"\\ud800"'); +assertEq(JSON.stringify("\ud937"), '"\\ud937"'); +assertEq(JSON.stringify("\uda20"), '"\\uda20"'); +assertEq(JSON.stringify("\udbff"), '"\\udbff"'); + +assertEq(JSON.stringify("\udc00"), '"\\udc00"'); +assertEq(JSON.stringify("\udddd"), '"\\udddd"'); +assertEq(JSON.stringify("\udeaf"), '"\\udeaf"'); +assertEq(JSON.stringify("\udfff"), '"\\udfff"'); +assertEq(JSON.stringify("\ue000"), '"\ue000"'); + +assertEq(JSON.stringify("\ud7ffa"), '"\ud7ffa"'); +assertEq(JSON.stringify("\ud800a"), '"\\ud800a"'); +assertEq(JSON.stringify("\ud937a"), '"\\ud937a"'); +assertEq(JSON.stringify("\uda20a"), '"\\uda20a"'); +assertEq(JSON.stringify("\udbffa"), '"\\udbffa"'); + +assertEq(JSON.stringify("\udc00a"), '"\\udc00a"'); +assertEq(JSON.stringify("\udddda"), '"\\udddda"'); +assertEq(JSON.stringify("\udeafa"), '"\\udeafa"'); +assertEq(JSON.stringify("\udfffa"), '"\\udfffa"'); +assertEq(JSON.stringify("\ue000a"), '"\ue000a"'); + +assertEq(JSON.stringify("\ud7ff\ud800"), '"\ud7ff\\ud800"'); +assertEq(JSON.stringify("\ud800\ud800"), '"\\ud800\\ud800"'); +assertEq(JSON.stringify("\ud937\ud800"), '"\\ud937\\ud800"'); +assertEq(JSON.stringify("\uda20\ud800"), '"\\uda20\\ud800"'); +assertEq(JSON.stringify("\udbff\ud800"), '"\\udbff\\ud800"'); + +assertEq(JSON.stringify("\udc00\ud800"), '"\\udc00\\ud800"'); +assertEq(JSON.stringify("\udddd\ud800"), '"\\udddd\\ud800"'); +assertEq(JSON.stringify("\udeaf\ud800"), '"\\udeaf\\ud800"'); +assertEq(JSON.stringify("\udfff\ud800"), '"\\udfff\\ud800"'); +assertEq(JSON.stringify("\ue000\ud800"), '"\ue000\\ud800"'); + +assertEq(JSON.stringify("\ud7ff\udc00"), '"\ud7ff\\udc00"'); +assertEq(JSON.stringify("\ud800\udc00"), '"\ud800\udc00"'); +assertEq(JSON.stringify("\ud937\udc00"), '"\ud937\udc00"'); +assertEq(JSON.stringify("\uda20\udc00"), '"\uda20\udc00"'); +assertEq(JSON.stringify("\udbff\udc00"), '"\udbff\udc00"'); + +assertEq(JSON.stringify("\udc00\udc00"), '"\\udc00\\udc00"'); +assertEq(JSON.stringify("\udddd\udc00"), '"\\udddd\\udc00"'); +assertEq(JSON.stringify("\udeaf\udc00"), '"\\udeaf\\udc00"'); +assertEq(JSON.stringify("\udfff\udc00"), '"\\udfff\\udc00"'); +assertEq(JSON.stringify("\ue000\udc00"), '"\ue000\\udc00"'); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/stringify-toJSON-arguments.js b/js/src/tests/non262/JSON/stringify-toJSON-arguments.js new file mode 100644 index 0000000000..7c2013d588 --- /dev/null +++ b/js/src/tests/non262/JSON/stringify-toJSON-arguments.js @@ -0,0 +1,34 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +var gTestfile = 'stringify-toJSON-arguments.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 584909; +var summary = "Arguments when an object's toJSON method is called"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var obj = + { + p: { + toJSON: function(key) + { + assertEq(arguments.length, 1); + assertEq(key, "p"); + return 17; + } + } + }; + +assertEq(JSON.stringify(obj), '{"p":17}'); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/stringify.js b/js/src/tests/non262/JSON/stringify.js new file mode 100644 index 0000000000..3b21474206 --- /dev/null +++ b/js/src/tests/non262/JSON/stringify.js @@ -0,0 +1,87 @@ +function assertStringify(v, expect) +{ + assertEq(JSON.stringify(v), expect); +} + +assertStringify({}, "{}"); +assertStringify([], "[]"); +assertStringify({"foo":"bar"}, '{"foo":"bar"}'); +assertStringify({"null":null}, '{"null":null}'); +assertStringify({"five":5}, '{"five":5}'); +assertStringify({"five":5, "six":6}, '{"five":5,"six":6}'); +assertStringify({"x":{"y":"z"}}, '{"x":{"y":"z"}}'); +assertStringify({"w":{"x":{"y":"z"}}}, '{"w":{"x":{"y":"z"}}}'); +assertStringify([1,2,3], '[1,2,3]'); +assertStringify({"w":{"x":{"y":[1,2,3]}}}, '{"w":{"x":{"y":[1,2,3]}}}'); +assertStringify({"false":false}, '{"false":false}'); +assertStringify({"true":true}, '{"true":true}'); +assertStringify({"child has two members": {"this":"one", 2:"and this one"}}, + '{"child has two members":{"2":"and this one","this":"one"}}'); +assertStringify({"x":{"a":"b","c":{"y":"z"},"f":"g"}}, + '{"x":{"a":"b","c":{"y":"z"},"f":"g"}}'); +assertStringify({"x":[1,{"y":"z"},3]}, '{"x":[1,{"y":"z"},3]}'); +assertStringify([new String("hmm")], '["hmm"]'); +assertStringify([new Boolean(true)], '[true]'); +assertStringify([new Number(42)], '[42]'); +assertStringify([new Date(Date.UTC(1978, 8, 13, 12, 24, 34, 23))], + '["1978-09-13T12:24:34.023Z"]'); +assertStringify([1,,3], '[1,null,3]'); +assertStringify({"mm\"mm":"hmm"}, '{"mm\\\"mm":"hmm"}'); +assertStringify({"mm\"mm\"mm":"hmm"}, '{"mm\\\"mm\\\"mm":"hmm"}'); +assertStringify({'"':"hmm"}, '{"\\\"":"hmm"}'); +assertStringify({'\\':"hmm"}, '{"\\\\":"hmm"}'); +assertStringify({'mmm\\mmm':"hmm"}, '{"mmm\\\\mmm":"hmm"}'); +assertStringify({'mmm\\mmm\\mmm':"hmm"}, '{"mmm\\\\mmm\\\\mmm":"hmm"}'); +assertStringify({"mm\u000bmm":"hmm"}, '{"mm\\u000bmm":"hmm"}'); +assertStringify({"mm\u0000mm":"hmm"}, '{"mm\\u0000mm":"hmm"}'); +assertStringify({"\u0000\u000b":""}, '{"\\u0000\\u000b":""}'); +assertStringify({"\u000b\ufdfd":"hmm"}, '{"\\u000b\ufdfd":"hmm"}'); +assertStringify({"\u000b\ufdfd":"h\xfc\ufdfdm"}, '{"\\u000b\ufdfd":"h\xfc\ufdfdm"}'); + +var x = {"free":"variable"}; +assertStringify(x, '{"free":"variable"}'); +assertStringify({"y":x}, '{"y":{"free":"variable"}}'); + +// array prop +assertStringify({ a: [1,2,3] }, '{"a":[1,2,3]}'); + +assertStringify({"y": { foo: function(hmm) { return hmm; } } }, '{"y":{}}'); + +// test toJSON +var hmm = { toJSON: function() { return {"foo":"bar"} } }; +assertStringify({"hmm":hmm}, '{"hmm":{"foo":"bar"}}'); +assertStringify(hmm, '{"foo":"bar"}'); // on the root + +// toJSON on prototype +var Y = function() { + this.not = "there?"; + this.d = "e"; +}; +Y.prototype = { + not: "there?", + toJSON: function() { return {"foo":"bar"}} +}; +var y = new Y(); +assertStringify(y.toJSON(), '{"foo":"bar"}'); +assertStringify(y, '{"foo":"bar"}'); + +// return undefined from toJSON +assertStringify({"hmm": { toJSON: function() { return; } } }, '{}'); + +// array with named prop +var x = new Array(); +x[0] = 1; +x.foo = "bar"; +assertStringify(x, '[1]'); + +// prototype +var X = function() { this.a = "b" }; +X.prototype = { c: "d" }; +assertStringify(new X(), '{"a":"b"}'); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/JSON/trailing-comma.js b/js/src/tests/non262/JSON/trailing-comma.js new file mode 100644 index 0000000000..0dc20e71a0 --- /dev/null +++ b/js/src/tests/non262/JSON/trailing-comma.js @@ -0,0 +1,32 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +var gTestfile = 'trailing-comma.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 564621; +var summary = 'JSON.parse should reject {"a" : "b",} or [1,]'; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +testJSON('[]', false); +testJSON('[1]', false); +testJSON('["a"]', false); +testJSON('{}', false); +testJSON('{"a":1}', false); +testJSON('{"a":"b"}', false); +testJSON('{"a":true}', false); +testJSON('[{}]', false); + +testJSON('[1,]', true); +testJSON('["a",]', true); +testJSON('{,}', true); +testJSON('{"a":1,}', true); +testJSON('{"a":"b",}', true); +testJSON('{"a":true,}', true); +testJSON('[{,}]', true); +testJSON('[[1,]]', true); +testJSON('[{"a":"b",}]', true); diff --git a/js/src/tests/non262/Map/NaN-as-key.js b/js/src/tests/non262/Map/NaN-as-key.js new file mode 100644 index 0000000000..6fa5ee67e9 --- /dev/null +++ b/js/src/tests/non262/Map/NaN-as-key.js @@ -0,0 +1,55 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 722260; +var summary = 'All NaNs must be treated as identical keys for Map'; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +/* Avoid constant-folding that would happen were |undefined| to be used. */ +var key = -/a/g.missingProperty; + +var m = new Map(); +m.set(key, 17); +assertEq(m.get(key), 17); +assertEq(m.get(-key), 17); +assertEq(m.get(NaN), 17); + +m.delete(-key); +assertEq(m.has(key), false); +assertEq(m.has(-key), false); +assertEq(m.has(NaN), false); + +m.set(-key, 17); +assertEq(m.get(key), 17); +assertEq(m.get(-key), 17); +assertEq(m.get(NaN), 17); + +m.delete(NaN); +assertEq(m.has(key), false); +assertEq(m.has(-key), false); +assertEq(m.has(NaN), false); + +m.set(NaN, 17); +assertEq(m.get(key), 17); +assertEq(m.get(-key), 17); +assertEq(m.get(NaN), 17); + +m.delete(key); +assertEq(m.has(key), false); +assertEq(m.has(-key), false); +assertEq(m.has(NaN), false); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Map/browser.js b/js/src/tests/non262/Map/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Map/constructor-iterator-close.js b/js/src/tests/non262/Map/constructor-iterator-close.js new file mode 100644 index 0000000000..084e6cb257 --- /dev/null +++ b/js/src/tests/non262/Map/constructor-iterator-close.js @@ -0,0 +1,293 @@ +var BUGNUMBER = 1180306; +var summary = 'Map/Set/WeakMap/WeakSet constructor should close iterator on error'; + +print(BUGNUMBER + ": " + summary); + +function test(ctors, { nextVal=undefined, + nextThrowVal=undefined, + modifier=undefined, + exceptionVal=undefined, + exceptionType=undefined, + closed=true }) { + function getIterable() { + let iterable = { + closed: false, + [Symbol.iterator]() { + let iterator = { + first: true, + next() { + if (this.first) { + this.first = false; + if (nextThrowVal) + throw nextThrowVal; + return nextVal; + } + return { value: undefined, done: true }; + }, + return() { + iterable.closed = true; + return {}; + } + }; + if (modifier) + modifier(iterator, iterable); + + return iterator; + } + }; + return iterable; + } + + for (let ctor of ctors) { + let iterable = getIterable(); + if (exceptionVal) { + let caught = false; + try { + new ctor(iterable); + } catch (e) { + assertEq(e, exceptionVal); + caught = true; + } + assertEq(caught, true); + } else if (exceptionType) { + assertThrowsInstanceOf(() => new ctor(iterable), exceptionType); + } else { + new ctor(iterable); + } + assertEq(iterable.closed, closed); + } +} + +// == Error cases with close == + +// ES 2017 draft 23.1.1.1 Map step 8.d.ii. +// ES 2017 draft 23.3.1.1 WeakMap step 8.d.ii. +test([Map, WeakMap], { + nextVal: { value: "non object", done: false }, + exceptionType: TypeError, + closed: true, +}); + +// ES 2017 draft 23.1.1.1 Map step 8.f. +// ES 2017 draft 23.3.1.1 WeakMap step 8.f. +test([Map, WeakMap], { + nextVal: { value: { get 0() { throw "0 getter throws"; } }, done: false }, + exceptionVal: "0 getter throws", + closed: true, +}); + +// ES 2017 draft 23.1.1.1 Map step 8.h. +// ES 2017 draft 23.3.1.1 WeakMap step 8.h. +test([Map, WeakMap], { + nextVal: { value: { 0: {}, get 1() { throw "1 getter throws"; } }, done: false }, + exceptionVal: "1 getter throws", + closed: true, +}); + +// ES 2017 draft 23.1.1.1 Map step 8.j. +// ES 2017 draft 23.3.1.1 WeakMap step 8.j. +class MyMap extends Map { + set(k, v) { + throw "setter throws"; + } +} +class MyWeakMap extends WeakMap { + set(k, v) { + throw "setter throws"; + } +} +test([MyMap, MyWeakMap], { + nextVal: { value: [{}, {}], done: false }, + exceptionVal: "setter throws", + closed: true, +}); + +// ES 2017 draft 23.2.1.1 Set step 8.e. +// ES 2017 draft 23.4.1.1 WeakSet step 8.e. +class MySet extends Set { + add(v) { + throw "adder throws"; + } +} +class MyWeakSet extends WeakSet { + add(v) { + throw "adder throws"; + } +} +test([MySet, MyWeakSet], { + nextVal: { value: {}, done: false }, + exceptionVal: "adder throws", + closed: true, +}); + +// ES 2021 draft 7.4.6 step 5. +// if GetMethod fails, the thrown value should be ignored. +test([MyMap, MyWeakMap], { + nextVal: { value: [{}, {}], done: false }, + modifier: (iterator, iterable) => { + Object.defineProperty(iterator, "return", { + get: function() { + iterable.closed = true; + throw "return getter throws"; + } + }); + }, + exceptionVal: "setter throws", + closed: true, +}); +test([MySet, MyWeakSet], { + nextVal: { value: [{}, {}], done: false }, + modifier: (iterator, iterable) => { + Object.defineProperty(iterator, "return", { + get: function() { + iterable.closed = true; + throw "return getter throws"; + } + }); + }, + exceptionVal: "adder throws", + closed: true, +}); +test([MyMap, MyWeakMap], { + nextVal: { value: [{}, {}], done: false }, + modifier: (iterator, iterable) => { + Object.defineProperty(iterator, "return", { + get: function() { + iterable.closed = true; + return "non object"; + } + }); + }, + exceptionVal: "setter throws", + closed: true, +}); +test([MySet, MyWeakSet], { + nextVal: { value: [{}, {}], done: false }, + modifier: (iterator, iterable) => { + Object.defineProperty(iterator, "return", { + get: function() { + iterable.closed = true; + return "non object"; + } + }); + }, + exceptionVal: "adder throws", + closed: true, +}); +test([MyMap, MyWeakMap], { + nextVal: { value: [{}, {}], done: false }, + modifier: (iterator, iterable) => { + Object.defineProperty(iterator, "return", { + get: function() { + iterable.closed = true; + // Non callable. + return {}; + } + }); + }, + exceptionVal: "setter throws", + closed: true, +}); +test([MySet, MyWeakSet], { + nextVal: { value: [{}, {}], done: false }, + modifier: (iterator, iterable) => { + Object.defineProperty(iterator, "return", { + get: function() { + iterable.closed = true; + // Non callable. + return {}; + } + }); + }, + exceptionVal: "adder throws", + closed: true, +}); + +// ES 2017 draft 7.4.6 steps 6. +// if return method throws, the thrown value should be ignored. +test([MyMap, MyWeakMap], { + nextVal: { value: [{}, {}], done: false }, + modifier: (iterator, iterable) => { + iterator.return = function() { + iterable.closed = true; + throw "return throws"; + }; + }, + exceptionVal: "setter throws", + closed: true, +}); +test([MySet, MyWeakSet], { + nextVal: { value: [{}, {}], done: false }, + modifier: (iterator, iterable) => { + iterator.return = function() { + iterable.closed = true; + throw "return throws"; + }; + }, + exceptionVal: "adder throws", + closed: true, +}); + +test([MyMap, MyWeakMap], { + nextVal: { value: [{}, {}], done: false }, + modifier: (iterator, iterable) => { + iterator.return = function() { + iterable.closed = true; + return "non object"; + }; + }, + exceptionVal: "setter throws", + closed: true, +}); +test([MySet, MyWeakSet], { + nextVal: { value: [{}, {}], done: false }, + modifier: (iterator, iterable) => { + iterator.return = function() { + iterable.closed = true; + return "non object"; + }; + }, + exceptionVal: "adder throws", + closed: true, +}); + +// == Error cases without close == + +// ES 2017 draft 23.1.1.1 Map step 8.a. +// ES 2017 draft 23.3.1.1 WeakMap step 8.a. +// ES 2017 draft 23.2.1.1 Set step 8.a. +// ES 2017 draft 23.4.1.1 WeakSet step 8.a. +test([Map, WeakMap, Set, WeakSet], { + nextThrowVal: "next throws", + exceptionVal: "next throws", + closed: false, +}); +test([Map, WeakMap, Set, WeakSet], { + nextVal: { value: {}, get done() { throw "done getter throws"; } }, + exceptionVal: "done getter throws", + closed: false, +}); + +// ES 2017 draft 23.1.1.1 Map step 8.c. +// ES 2017 draft 23.3.1.1 WeakMap step 8.c. +// ES 2017 draft 23.2.1.1 Set step 8.c. +// ES 2017 draft 23.4.1.1 WeakSet step 8.c. +test([Map, WeakMap, Set, WeakSet], { + nextVal: { get value() { throw "value getter throws"; }, done: false }, + exceptionVal: "value getter throws", + closed: false, +}); + +// == Successful cases == + +test([Map, WeakMap], { + nextVal: { value: [{}, {}], done: false }, + closed: false, +}); +test([Set, WeakSet], { + nextVal: { value: {}, done: false }, + closed: false, +}); + +if (typeof reportCompare === 'function') + reportCompare(true, true); diff --git a/js/src/tests/non262/Map/constructor-iterator-primitive.js b/js/src/tests/non262/Map/constructor-iterator-primitive.js new file mode 100644 index 0000000000..e1fff5c3c9 --- /dev/null +++ b/js/src/tests/non262/Map/constructor-iterator-primitive.js @@ -0,0 +1,34 @@ +var BUGNUMBER = 1021835; +var summary = "Returning non-object from @@iterator should throw"; + +print(BUGNUMBER + ": " + summary); + +let ctors = [ + Map, + Set, + WeakMap, + WeakSet +]; + +let primitives = [ + 1, + true, + undefined, + null, + "foo", + Symbol.iterator +]; + +for (let ctor of ctors) { + for (let primitive of primitives) { + let arg = { + [Symbol.iterator]() { + return primitive; + } + }; + assertThrowsInstanceOf(() => new ctor(arg), TypeError); + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Map/forEach-selfhosted-behavior.js b/js/src/tests/non262/Map/forEach-selfhosted-behavior.js new file mode 100644 index 0000000000..ed4d8b57f8 --- /dev/null +++ b/js/src/tests/non262/Map/forEach-selfhosted-behavior.js @@ -0,0 +1,51 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 987243; +var summary = "Don't use .call(...) in the self-hosted Map.prototype.forEach"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var functionCall = Function.prototype.call; + +function throwSyntaxError() +{ + throw new SyntaxError("Function.prototype.call incorrectly called"); +} + +function lalala() {} + +Function.prototype.call = throwSyntaxError; + +new Map().forEach(throwSyntaxError); +new Map([[1, 2]]).forEach(lalala); +new Map([[1, 2], [3, 4]]).forEach(lalala); + +Function.prototype.call = function() { this.set(42, "fnord"); }; + +new Map().forEach(throwSyntaxError); +new Map([[1, 2]]).forEach(lalala); +new Map([[1, 2], [3, 4]]).forEach(lalala); + +var callCount = 0; +Function.prototype.call = function() { callCount++; }; + +new Map().forEach(throwSyntaxError); +new Map([[1, 2]]).forEach(lalala); +new Map([[1, 2], [3, 4]]).forEach(lalala); + +assertEq(callCount, 0); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Map/getter-name.js b/js/src/tests/non262/Map/getter-name.js new file mode 100644 index 0000000000..08f7890c75 --- /dev/null +++ b/js/src/tests/non262/Map/getter-name.js @@ -0,0 +1,10 @@ +var BUGNUMBER = 1180290; +var summary = 'Map getters should have get prefix'; + +print(BUGNUMBER + ": " + summary); + +assertEq(Object.getOwnPropertyDescriptor(Map, Symbol.species).get.name, "get [Symbol.species]"); +assertEq(Object.getOwnPropertyDescriptor(Map.prototype, "size").get.name, "get size"); + +if (typeof reportCompare === 'function') + reportCompare(true, true); diff --git a/js/src/tests/non262/Map/iterable.js b/js/src/tests/non262/Map/iterable.js new file mode 100644 index 0000000000..cf6b7228ab --- /dev/null +++ b/js/src/tests/non262/Map/iterable.js @@ -0,0 +1,28 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +let length; +let iterable = { + [Symbol.iterator]() { return this; }, + next() { length = arguments.length; return {done: true}; } +}; + +new Map(iterable); +// ensure no arguments are passed to next() during construction (Bug 1197095) +assertEq(length, 0); + +let typeofThis; +Object.defineProperty(Number.prototype, Symbol.iterator, { + value() { + "use strict"; + typeofThis = typeof this; + return { next() { return {done: true}; } }; + } +}); + +new Map(0); +// ensure that iterable objects retain their type (Bug 1197094) +assertEq(typeofThis, "number"); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Map/iterator-thisv-error.js b/js/src/tests/non262/Map/iterator-thisv-error.js new file mode 100644 index 0000000000..cc85c90f25 --- /dev/null +++ b/js/src/tests/non262/Map/iterator-thisv-error.js @@ -0,0 +1,24 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +function test(fn, thisv) { + var message; + try { + fn.call(thisv); + } catch (e) { + message = e.message; + } + + assertEq(/^\w+ method called on incompatible.+/.test(message), true); + assertEq(message.includes("std_"), false); +} + +for (var thisv of [null, undefined, false, true, 0, ""]) { + test(Map.prototype.values, thisv); + test(Map.prototype.keys, thisv); + test(Map.prototype.entries, thisv); + test(Map.prototype[Symbol.iterator], thisv); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Map/record-tuple.js b/js/src/tests/non262/Map/record-tuple.js new file mode 100644 index 0000000000..92c9d68414 --- /dev/null +++ b/js/src/tests/non262/Map/record-tuple.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(!this.hasOwnProperty("Record")) + +function test(input, query, same) { + assertEq(set(input).has(query), same); + assertEq(new Map([[input, 1]]).has(query), same); + if (same) assertEq(new Map([[input, 1]]).get(query), 1); +} +function first(it) { + for (const v of it) return v; +} +function set(v) { + return new Set([v]); +} + + +test(#[0, 1], #[0, 1], true); +test(#[0, 1], #[1, 0], false); + +test(#{x: 1}, #{x: 1}, true); +test(#{x: 1}, #{y: 1}, false); +test(#{x: 1}, #{x: 0}, false); +test(#{x: 0, y: 1}, #{x: 0, y: 1}, true); +test(#{x: 0, y: 1}, #{y: 1, x: 0}, true); +test(#{x: 0, y: 1}, #{x: 1, y: 0}, false); +test(#{x: 0, y: 1}, #{x: 0, y: 0}, false); + +test(#[NaN], #[NaN], true); +test(#{x: NaN}, #{x: NaN}, true); +test(#[+0], #[-0], true); +test(#{x: +0}, #{x: -0}, true); +assertEq(Object.is(first(set(#[+0]))[0], +0), true); +assertEq(Object.is(first(set(#[-0]))[0], -0), true); +assertEq(Object.is(first(set(#{x: +0})).x, +0), true); +assertEq(Object.is(first(set(#{x: -0})).x, -0), true); + +// Test ropes. +test(#["ab" + String.fromCodePoint(67)], #["ab" + String.fromCodePoint(67)], true); +test(#{ x: "ab" + String.fromCodePoint(67) }, #{ x: "ab" + String.fromCodePoint(67) }, true); +test(#["ab" + String.fromCodePoint(67)], #["ab" + String.fromCodePoint(68)], false); +test(#{ x: "ab" + String.fromCodePoint(67) }, #{ x: "ab" + String.fromCodePoint(68) }, false); + +if (typeof reportCompare === "function") reportCompare(0, 0); diff --git a/js/src/tests/non262/Map/shell.js b/js/src/tests/non262/Map/shell.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Map/symbols.js b/js/src/tests/non262/Map/symbols.js new file mode 100644 index 0000000000..30589a9732 --- /dev/null +++ b/js/src/tests/non262/Map/symbols.js @@ -0,0 +1,33 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +var m = new Map; + +// Symbols can be Map keys. +var sym = Symbol(); +m.set(sym, "zero"); +assertEq(m.has(sym), true); +assertEq(m.get(sym), "zero"); +assertEq(m.has(Symbol()), false); +assertEq(m.get(Symbol()), undefined); +assertEq([...m][0][0], sym); +m.set(sym, "replaced"); +assertEq(m.get(sym), "replaced"); +m.delete(sym); +assertEq(m.has(sym), false); +assertEq(m.size, 0); + +// Symbols returned by Symbol.for() can be Map keys. +for (var word of "that that is is that that is not is not is that not it".split(' ')) { + sym = Symbol.for(word); + m.set(sym, (m.get(sym) || 0) + 1); +} +assertDeepEq([...m], [ + [Symbol.for("that"), 5], + [Symbol.for("is"), 5], + [Symbol.for("not"), 3], + [Symbol.for("it"), 1] +]); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Math/15.8.1.js b/js/src/tests/non262/Math/15.8.1.js new file mode 100644 index 0000000000..269b602e5d --- /dev/null +++ b/js/src/tests/non262/Math/15.8.1.js @@ -0,0 +1,97 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + File Name: 15.8.1.js + ECMA Section: 15.8.1.js Value Properties of the Math Object + 15.8.1.1 E + 15.8.1.2 LN10 + 15.8.1.3 LN2 + 15.8.1.4 LOG2E + 15.8.1.5 LOG10E + 15.8.1.6 PI + 15.8.1.7 SQRT1_2 + 15.8.1.8 SQRT2 + Description: verify the values of some math constants + Author: christine@netscape.com + Date: 7 july 1997 + +*/ +var SECTION = "15.8.1" + var TITLE = "Value Properties of the Math Object"; + +writeHeaderToLog( SECTION + " "+ TITLE); + + +new TestCase( "Math.E", + 2.7182818284590452354, + Math.E ); + +new TestCase( "typeof Math.E", + "number", + typeof Math.E ); + +new TestCase( "Math.LN10", + 2.302585092994046, + Math.LN10 ); + +new TestCase( "typeof Math.LN10", + "number", + typeof Math.LN10 ); + +new TestCase( "Math.LN2", + 0.6931471805599453, + Math.LN2 ); + +new TestCase( "typeof Math.LN2", + "number", + typeof Math.LN2 ); + +new TestCase( "Math.LOG2E", + 1.4426950408889634, + Math.LOG2E ); + +new TestCase( "typeof Math.LOG2E", + "number", + typeof Math.LOG2E ); + +new TestCase( "Math.LOG10E", + 0.4342944819032518, + Math.LOG10E); + +new TestCase( "typeof Math.LOG10E", + "number", + typeof Math.LOG10E); + +new TestCase( "Math.PI", + 3.14159265358979323846, + Math.PI ); + +new TestCase( "typeof Math.PI", + "number", + typeof Math.PI ); + +new TestCase( "Math.SQRT1_2", + 0.7071067811865476, + Math.SQRT1_2); + +new TestCase( "typeof Math.SQRT1_2", + "number", + typeof Math.SQRT1_2); + +new TestCase( "Math.SQRT2", + 1.4142135623730951, + Math.SQRT2 ); + +new TestCase( "typeof Math.SQRT2", + "number", + typeof Math.SQRT2 ); + +new TestCase( "var MATHPROPS='';for( p in Math ){ MATHPROPS +=p; };MATHPROPS", + "", + eval("var MATHPROPS='';for( p in Math ){ MATHPROPS +=p; };MATHPROPS") ); + +test(); diff --git a/js/src/tests/non262/Math/15.8.2.13.js b/js/src/tests/non262/Math/15.8.2.13.js new file mode 100644 index 0000000000..10eeca88ab --- /dev/null +++ b/js/src/tests/non262/Math/15.8.2.13.js @@ -0,0 +1,350 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + File Name: 15.8.2.13.js + ECMA Section: 15.8.2.13 Math.pow(x, y) + Description: return an approximation to the result of x + to the power of y. there are many special cases; + refer to the spec. + Author: christine@netscape.com + Date: 9 july 1997 +*/ + +var SECTION = "15.8.2.13"; +var TITLE = "Math.pow(x, y)"; +var BUGNUMBER="77141"; + +printBugNumber(BUGNUMBER); + +writeHeaderToLog( SECTION + " "+ TITLE); + +new TestCase( + "Math.pow.length", + 2, + Math.pow.length ); + +new TestCase( + "Math.pow()", + Number.NaN, + Math.pow() ); + +new TestCase( + "Math.pow(null, null)", + 1, + Math.pow(null,null) ); + +new TestCase( + "Math.pow(void 0, void 0)", + Number.NaN, + Math.pow(void 0, void 0)); + +new TestCase( + "Math.pow(true, false)", + 1, + Math.pow(true, false) ); + +new TestCase( + "Math.pow(false,true)", + 0, + Math.pow(false,true) ); + +new TestCase( + "Math.pow('2','32')", + 4294967296, + Math.pow('2','32') ); + +new TestCase( + "Math.pow(1,NaN)", + Number.NaN, + Math.pow(1,Number.NaN) ); + +new TestCase( + "Math.pow(0,NaN)", + Number.NaN, + Math.pow(0,Number.NaN) ); + +new TestCase( + "Math.pow(NaN,0)", + 1, + Math.pow(Number.NaN,0) ); + +new TestCase( + "Math.pow(NaN,-0)", + 1, + Math.pow(Number.NaN,-0) ); + +new TestCase( + "Math.pow(NaN,1)", + Number.NaN, + Math.pow(Number.NaN, 1) ); + +new TestCase( + "Math.pow(NaN,.5)", + Number.NaN, + Math.pow(Number.NaN, .5) ); + +new TestCase( + "Math.pow(1.00000001, Infinity)", + Number.POSITIVE_INFINITY, + Math.pow(1.00000001, Number.POSITIVE_INFINITY) ); + +new TestCase( + "Math.pow(1.00000001, -Infinity)", + 0, + Math.pow(1.00000001, Number.NEGATIVE_INFINITY) ); + +new TestCase( + "Math.pow(-1.00000001, Infinity)", + Number.POSITIVE_INFINITY, + Math.pow(-1.00000001,Number.POSITIVE_INFINITY) ); + +new TestCase( + "Math.pow(-1.00000001, -Infinity)", + 0, + Math.pow(-1.00000001,Number.NEGATIVE_INFINITY) ); + +new TestCase( + "Math.pow(1, Infinity)", + Number.NaN, + Math.pow(1, Number.POSITIVE_INFINITY) ); + +new TestCase( + "Math.pow(1, -Infinity)", + Number.NaN, + Math.pow(1, Number.NEGATIVE_INFINITY) ); + +new TestCase( + "Math.pow(-1, Infinity)", + Number.NaN, + Math.pow(-1, Number.POSITIVE_INFINITY) ); + +new TestCase( + "Math.pow(-1, -Infinity)", + Number.NaN, + Math.pow(-1, Number.NEGATIVE_INFINITY) ); + +new TestCase( + "Math.pow(.0000000009, Infinity)", + 0, + Math.pow(.0000000009, Number.POSITIVE_INFINITY) ); + +new TestCase( + "Math.pow(-.0000000009, Infinity)", + 0, + Math.pow(-.0000000009, Number.POSITIVE_INFINITY) ); + +new TestCase( + "Math.pow(.0000000009, -Infinity)", + Number.POSITIVE_INFINITY, + Math.pow(-.0000000009, Number.NEGATIVE_INFINITY) ); + +new TestCase( + "Math.pow(Infinity, .00000000001)", + Number.POSITIVE_INFINITY, + Math.pow(Number.POSITIVE_INFINITY,.00000000001) ); + +new TestCase( + "Math.pow(Infinity, 1)", + Number.POSITIVE_INFINITY, + Math.pow(Number.POSITIVE_INFINITY, 1) ); + +new TestCase( + "Math.pow(Infinity, -.00000000001)", + 0, + Math.pow(Number.POSITIVE_INFINITY, -.00000000001) ); + +new TestCase( + "Math.pow(Infinity, -1)", + 0, + Math.pow(Number.POSITIVE_INFINITY, -1) ); + +new TestCase( + "Math.pow(-Infinity, 1)", + Number.NEGATIVE_INFINITY, + Math.pow(Number.NEGATIVE_INFINITY, 1) ); + +new TestCase( + "Math.pow(-Infinity, 333)", + Number.NEGATIVE_INFINITY, + Math.pow(Number.NEGATIVE_INFINITY, 333) ); + +new TestCase( + "Math.pow(Infinity, 2)", + Number.POSITIVE_INFINITY, + Math.pow(Number.POSITIVE_INFINITY, 2) ); + +new TestCase( + "Math.pow(-Infinity, 666)", + Number.POSITIVE_INFINITY, + Math.pow(Number.NEGATIVE_INFINITY, 666) ); + +new TestCase( + "Math.pow(-Infinity, 0.5)", + Number.POSITIVE_INFINITY, + Math.pow(Number.NEGATIVE_INFINITY, 0.5) ); + +new TestCase( + "Math.pow(-Infinity, Infinity)", + Number.POSITIVE_INFINITY, + Math.pow(Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY) ); + +new TestCase( + "Math.pow(-Infinity, -1)", + -0, + Math.pow(Number.NEGATIVE_INFINITY, -1) ); + +new TestCase( + "Infinity/Math.pow(-Infinity, -1)", + -Infinity, + Infinity/Math.pow(Number.NEGATIVE_INFINITY, -1) ); + +new TestCase( + "Math.pow(-Infinity, -3)", + -0, + Math.pow(Number.NEGATIVE_INFINITY, -3) ); + +new TestCase( + "Math.pow(-Infinity, -2)", + 0, + Math.pow(Number.NEGATIVE_INFINITY, -2) ); + +new TestCase( + "Math.pow(-Infinity, -0.5)", + 0, + Math.pow(Number.NEGATIVE_INFINITY,-0.5) ); + +new TestCase( + "Math.pow(-Infinity, -Infinity)", + 0, + Math.pow(Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY) ); + +new TestCase( + "Math.pow(0, 1)", + 0, + Math.pow(0,1) ); + +new TestCase( + "Math.pow(0, 0)", + 1, + Math.pow(0,0) ); + +new TestCase( + "Math.pow(1, 0)", + 1, + Math.pow(1,0) ); + +new TestCase( + "Math.pow(-1, 0)", + 1, + Math.pow(-1,0) ); + +new TestCase( + "Math.pow(0, 0.5)", + 0, + Math.pow(0,0.5) ); + +new TestCase( + "Math.pow(0, 1000)", + 0, + Math.pow(0,1000) ); + +new TestCase( + "Math.pow(0, Infinity)", + 0, + Math.pow(0, Number.POSITIVE_INFINITY) ); + +new TestCase( + "Math.pow(0, -1)", + Number.POSITIVE_INFINITY, + Math.pow(0, -1) ); + +new TestCase( + "Math.pow(0, -0.5)", + Number.POSITIVE_INFINITY, + Math.pow(0, -0.5) ); + +new TestCase( + "Math.pow(0, -1000)", + Number.POSITIVE_INFINITY, + Math.pow(0, -1000) ); + +new TestCase( + "Math.pow(0, -Infinity)", + Number.POSITIVE_INFINITY, + Math.pow(0, Number.NEGATIVE_INFINITY) ); + +new TestCase( + "Math.pow(-0, 1)", + -0, + Math.pow(-0, 1) ); + +new TestCase( + "Math.pow(-0, 3)", + -0, + Math.pow(-0,3) ); + +new TestCase( + "Infinity/Math.pow(-0, 1)", + -Infinity, + Infinity/Math.pow(-0, 1) ); + +new TestCase( + "Infinity/Math.pow(-0, 3)", + -Infinity, + Infinity/Math.pow(-0,3) ); + +new TestCase( + "Math.pow(-0, 2)", + 0, + Math.pow(-0,2) ); + +new TestCase( + "Math.pow(-0, Infinity)", + 0, + Math.pow(-0, Number.POSITIVE_INFINITY) ); + +new TestCase( + "Math.pow(-0, -1)", + Number.NEGATIVE_INFINITY, + Math.pow(-0, -1) ); + +new TestCase( + "Math.pow(-0, -10001)", + Number.NEGATIVE_INFINITY, + Math.pow(-0, -10001) ); + +new TestCase( + "Math.pow(-0, -2)", + Number.POSITIVE_INFINITY, + Math.pow(-0, -2) ); + +new TestCase( + "Math.pow(-0, 0.5)", + 0, + Math.pow(-0, 0.5) ); + +new TestCase( + "Math.pow(-0, Infinity)", + 0, + Math.pow(-0, Number.POSITIVE_INFINITY) ); + +new TestCase( + "Math.pow(-1, 0.5)", + Number.NaN, + Math.pow(-1, 0.5) ); + +new TestCase( + "Math.pow(-1, NaN)", + Number.NaN, + Math.pow(-1, Number.NaN) ); + +new TestCase( + "Math.pow(-1, -0.5)", + Number.NaN, + Math.pow(-1, -0.5) ); + +test(); diff --git a/js/src/tests/non262/Math/15.8.2.16.js b/js/src/tests/non262/Math/15.8.2.16.js new file mode 100644 index 0000000000..1ad66d4e30 --- /dev/null +++ b/js/src/tests/non262/Math/15.8.2.16.js @@ -0,0 +1,96 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + File Name: 15.8.2.16.js + ECMA Section: 15.8.2.16 sin( x ) + Description: return an approximation to the sine of the + argument. argument is expressed in radians + Author: christine@netscape.com + Date: 7 july 1997 + +*/ +var SECTION = "15.8.2.16"; +var TITLE = "Math.sin(x)"; + +writeHeaderToLog( SECTION + " "+ TITLE); + +new TestCase( + "Math.sin.length", + 1, + Math.sin.length ); + +new TestCase( + "Math.sin()", + Number.NaN, + Math.sin() ); + +new TestCase( + "Math.sin(null)", + 0, + Math.sin(null) ); + +new TestCase( + "Math.sin(void 0)", + Number.NaN, + Math.sin(void 0) ); + +new TestCase( + "Math.sin(false)", + 0, + Math.sin(false) ); + +new TestCase( + "Math.sin('2.356194490192')", + 0.7071067811865, + Math.sin('2.356194490192') ); + +new TestCase( + "Math.sin(NaN)", + Number.NaN, + Math.sin(Number.NaN) ); + +new TestCase( + "Math.sin(0)", + 0, + Math.sin(0) ); + +new TestCase( + "Math.sin(-0)", + -0, + Math.sin(-0)); + +new TestCase( + "Math.sin(Infinity)", + Number.NaN, + Math.sin(Number.POSITIVE_INFINITY)); + +new TestCase( + "Math.sin(-Infinity)", + Number.NaN, + Math.sin(Number.NEGATIVE_INFINITY)); + +new TestCase( + "Math.sin(0.7853981633974)", + 0.7071067811865, + Math.sin(0.7853981633974)); + +new TestCase( + "Math.sin(1.570796326795)", + 1, + Math.sin(1.570796326795)); + +new TestCase( + "Math.sin(2.356194490192)", + 0.7071067811865, + Math.sin(2.356194490192)); + +new TestCase( + "Math.sin(3.14159265359)", + 0, + Math.sin(3.14159265359)); + +test(); diff --git a/js/src/tests/non262/Math/15.8.2.17.js b/js/src/tests/non262/Math/15.8.2.17.js new file mode 100644 index 0000000000..18b4a0a281 --- /dev/null +++ b/js/src/tests/non262/Math/15.8.2.17.js @@ -0,0 +1,181 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + File Name: 15.8.2.17.js + ECMA Section: 15.8.2.17 Math.sqrt(x) + Description: return an approximation to the squareroot of the argument. + special cases: + - if x is NaN return NaN + - if x < 0 return NaN + - if x == 0 return 0 + - if x == -0 return -0 + - if x == Infinity return Infinity + Author: christine@netscape.com + Date: 7 july 1997 +*/ + +var SECTION = "15.8.2.17"; +var TITLE = "Math.sqrt(x)"; + +writeHeaderToLog( SECTION + " "+ TITLE); + +new TestCase( + "Math.sqrt.length", + 1, + Math.sqrt.length ); + +new TestCase( + "Math.sqrt()", + Number.NaN, + Math.sqrt() ); + +new TestCase( + "Math.sqrt(void 0)", + Number.NaN, + Math.sqrt(void 0) ); + +new TestCase( + "Math.sqrt(null)", + 0, + Math.sqrt(null) ); + +new TestCase( + "Math.sqrt(true)", + 1, + Math.sqrt(1) ); + +new TestCase( + "Math.sqrt(false)", + 0, + Math.sqrt(false) ); + +new TestCase( + "Math.sqrt('225')", + 15, + Math.sqrt('225') ); + +new TestCase( + "Math.sqrt(NaN)", + Number.NaN, + Math.sqrt(Number.NaN) ); + +new TestCase( + "Math.sqrt(-Infinity)", + Number.NaN, + Math.sqrt(Number.NEGATIVE_INFINITY)); + +new TestCase( + "Math.sqrt(-1)", + Number.NaN, + Math.sqrt(-1)); + +new TestCase( + "Math.sqrt(-0.5)", + Number.NaN, + Math.sqrt(-0.5)); + +new TestCase( + "Math.sqrt(0)", + 0, + Math.sqrt(0)); + +new TestCase( + "Math.sqrt(-0)", + -0, + Math.sqrt(-0)); + +new TestCase( + "Infinity/Math.sqrt(-0)", + -Infinity, + Infinity/Math.sqrt(-0) ); + +new TestCase( + "Math.sqrt(Infinity)", + Number.POSITIVE_INFINITY, + Math.sqrt(Number.POSITIVE_INFINITY)); + +new TestCase( + "Math.sqrt(1)", + 1, + Math.sqrt(1)); + +new TestCase( + "Math.sqrt(2)", + Math.SQRT2, + Math.sqrt(2)); + +new TestCase( + "Math.sqrt(0.5)", + Math.SQRT1_2, + Math.sqrt(0.5)); + +new TestCase( + "Math.sqrt(4)", + 2, + Math.sqrt(4)); + +new TestCase( + "Math.sqrt(9)", + 3, + Math.sqrt(9)); + +new TestCase( + "Math.sqrt(16)", + 4, + Math.sqrt(16)); + +new TestCase( + "Math.sqrt(25)", + 5, + Math.sqrt(25)); + +new TestCase( + "Math.sqrt(36)", + 6, + Math.sqrt(36)); + +new TestCase( + "Math.sqrt(49)", + 7, + Math.sqrt(49)); + +new TestCase( + "Math.sqrt(64)", + 8, + Math.sqrt(64)); + +new TestCase( + "Math.sqrt(256)", + 16, + Math.sqrt(256)); + +new TestCase( + "Math.sqrt(10000)", + 100, + Math.sqrt(10000)); + +new TestCase( + "Math.sqrt(65536)", + 256, + Math.sqrt(65536)); + +new TestCase( + "Math.sqrt(0.09)", + 0.3, + Math.sqrt(0.09)); + +new TestCase( + "Math.sqrt(0.01)", + 0.1, + Math.sqrt(0.01)); + +new TestCase( + "Math.sqrt(0.00000001)", + 0.0001, + Math.sqrt(0.00000001)); + +test(); diff --git a/js/src/tests/non262/Math/15.8.2.18.js b/js/src/tests/non262/Math/15.8.2.18.js new file mode 100644 index 0000000000..574ec18b99 --- /dev/null +++ b/js/src/tests/non262/Math/15.8.2.18.js @@ -0,0 +1,111 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + File Name: 15.8.2.18.js + ECMA Section: 15.8.2.18 tan( x ) + Description: return an approximation to the tan of the + argument. argument is expressed in radians + special cases: + - if x is NaN result is NaN + - if x is 0 result is 0 + - if x is -0 result is -0 + - if x is Infinity or -Infinity result is NaN + Author: christine@netscape.com + Date: 7 july 1997 +*/ + +var SECTION = "15.8.2.18"; +var TITLE = "Math.tan(x)"; +var EXCLUDE = "true"; + +writeHeaderToLog( SECTION + " "+ TITLE); + +new TestCase( "Math.tan.length", + 1, + Math.tan.length ); + +new TestCase( "Math.tan()", + Number.NaN, + Math.tan() ); + +new TestCase( "Math.tan(void 0)", + Number.NaN, + Math.tan(void 0)); + +new TestCase( "Math.tan(null)", + 0, + Math.tan(null) ); + +new TestCase( "Math.tan(false)", + 0, + Math.tan(false) ); + +new TestCase( "Math.tan(NaN)", + Number.NaN, + Math.tan(Number.NaN) ); + +new TestCase( "Math.tan(0)", + 0, + Math.tan(0)); + +new TestCase( "Math.tan(-0)", + -0, + Math.tan(-0)); + +new TestCase( "Math.tan(Infinity)", + Number.NaN, + Math.tan(Number.POSITIVE_INFINITY)); + +new TestCase( "Math.tan(-Infinity)", + Number.NaN, + Math.tan(Number.NEGATIVE_INFINITY)); + +new TestCase( "Math.tan(Math.PI/4)", + 1, + Math.tan(Math.PI/4)); + +new TestCase( "Math.tan(3*Math.PI/4)", + -1, + Math.tan(3*Math.PI/4)); + +new TestCase( "Math.tan(Math.PI)", + -0, + Math.tan(Math.PI)); + +new TestCase( "Math.tan(5*Math.PI/4)", + 1, + Math.tan(5*Math.PI/4)); + +new TestCase( "Math.tan(7*Math.PI/4)", + -1, + Math.tan(7*Math.PI/4)); + +new TestCase( "Infinity/Math.tan(-0)", + -Infinity, + Infinity/Math.tan(-0) ); + +/* + Arctan (x) ~ PI/2 - 1/x for large x. For x = 1.6x10^16, 1/x is about the last binary digit of double precision PI/2. + That is to say, perturbing PI/2 by this much is about the smallest rounding error possible. + + This suggests that the answer Christine is getting and a real Infinity are "adjacent" results from the tangent function. I + suspect that tan (PI/2 + one ulp) is a negative result about the same size as tan (PI/2) and that this pair are the closest + results to infinity that the algorithm can deliver. + + In any case, my call is that the answer we're seeing is "right". I suggest the test pass on any result this size or larger. + = C = +*/ + +new TestCase( "Math.tan(3*Math.PI/2) >= 5443000000000000", + true, + Math.tan(3*Math.PI/2) >= 5443000000000000 ); + +new TestCase( "Math.tan(Math.PI/2) >= 5443000000000000", + true, + Math.tan(Math.PI/2) >= 5443000000000000 ); + +test(); diff --git a/js/src/tests/non262/Math/15.8.2.2.js b/js/src/tests/non262/Math/15.8.2.2.js new file mode 100644 index 0000000000..fef32b9e41 --- /dev/null +++ b/js/src/tests/non262/Math/15.8.2.2.js @@ -0,0 +1,120 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + File Name: 15.8.2.2.js + ECMA Section: 15.8.2.2 acos( x ) + Description: return an approximation to the arc cosine of the + argument. the result is expressed in radians and + range is from +0 to +PI. special cases: + - if x is NaN, return NaN + - if x > 1, the result is NaN + - if x < -1, the result is NaN + - if x == 1, the result is +0 + Author: christine@netscape.com + Date: 7 july 1997 +*/ +var SECTION = "15.8.2.2"; +var TITLE = "Math.acos()"; + +writeHeaderToLog( SECTION + " "+ TITLE); + +new TestCase( + "Math.acos.length", + 1, + Math.acos.length ); + +new TestCase( + "Math.acos(void 0)", + Number.NaN, + Math.acos(void 0) ); + +new TestCase( + "Math.acos()", + Number.NaN, + Math.acos() ); + +new TestCase( + "Math.acos(null)", + Math.PI/2, + Math.acos(null) ); + +new TestCase( + "Math.acos(NaN)", + Number.NaN, + Math.acos(Number.NaN) ); + +new TestCase( + "Math.acos(a string)", + Number.NaN, + Math.acos("a string") ); + +new TestCase( + "Math.acos('0')", + Math.PI/2, + Math.acos('0') ); + +new TestCase( + "Math.acos('1')", + 0, + Math.acos('1') ); + +new TestCase( + "Math.acos('-1')", + Math.PI, + Math.acos('-1') ); + +new TestCase( + "Math.acos(1.00000001)", + Number.NaN, + Math.acos(1.00000001) ); + +new TestCase( + "Math.acos(11.00000001)", + Number.NaN, + Math.acos(-1.00000001) ); + +new TestCase( + "Math.acos(1)", + 0, + Math.acos(1) ); + +new TestCase( + "Math.acos(-1)", + Math.PI, + Math.acos(-1) ); + +new TestCase( + "Math.acos(0)", + Math.PI/2, + Math.acos(0) ); + +new TestCase( + "Math.acos(-0)", + Math.PI/2, + Math.acos(-0) ); + +new TestCase( + "Math.acos(Math.SQRT1_2)", + Math.PI/4, + Math.acos(Math.SQRT1_2)); + +new TestCase( + "Math.acos(-Math.SQRT1_2)", + Math.PI/4*3, + Math.acos(-Math.SQRT1_2)); + +new TestCase( + "Math.acos(0.9999619230642)", + Math.PI/360, + Math.acos(0.9999619230642)); + +new TestCase( + "Math.acos(-3.0)", + Number.NaN, + Math.acos(-3.0)); + +test(); diff --git a/js/src/tests/non262/Math/15.8.2.3.js b/js/src/tests/non262/Math/15.8.2.3.js new file mode 100644 index 0000000000..750f22bb60 --- /dev/null +++ b/js/src/tests/non262/Math/15.8.2.3.js @@ -0,0 +1,122 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + File Name: 15.8.2.3.js + ECMA Section: 15.8.2.3 asin( x ) + Description: return an approximation to the arc sine of the + argument. the result is expressed in radians and + range is from -PI/2 to +PI/2. special cases: + - if x is NaN, the result is NaN + - if x > 1, the result is NaN + - if x < -1, the result is NaN + - if x == +0, the result is +0 + - if x == -0, the result is -0 + Author: christine@netscape.com + Date: 7 july 1997 + +*/ +var SECTION = "15.8.2.3"; +var TITLE = "Math.asin()"; + +writeHeaderToLog( SECTION + " "+ TITLE); + +new TestCase( + "Math.asin()", + Number.NaN, + Math.asin() ); + +new TestCase( + "Math.asin(void 0)", + Number.NaN, + Math.asin(void 0) ); + +new TestCase( + "Math.asin(null)", + 0, + Math.asin(null) ); + +new TestCase( + "Math.asin(NaN)", + Number.NaN, + Math.asin(Number.NaN) ); + +new TestCase( + "Math.asin('string')", + Number.NaN, + Math.asin("string") ); + +new TestCase( + "Math.asin('0')", + 0, + Math.asin("0") ); + +new TestCase( + "Math.asin('1')", + Math.PI/2, + Math.asin("1") ); + +new TestCase( + "Math.asin('-1')", + -Math.PI/2, + Math.asin("-1") ); + +new TestCase( + "Math.asin(Math.SQRT1_2+'')", + Math.PI/4, + Math.asin(Math.SQRT1_2+'') ); + +new TestCase( + "Math.asin(-Math.SQRT1_2+'')", + -Math.PI/4, + Math.asin(-Math.SQRT1_2+'') ); + +new TestCase( + "Math.asin(1.000001)", + Number.NaN, + Math.asin(1.000001) ); + +new TestCase( + "Math.asin(-1.000001)", + Number.NaN, + Math.asin(-1.000001) ); + +new TestCase( + "Math.asin(0)", + 0, + Math.asin(0) ); + +new TestCase( + "Math.asin(-0)", + -0, + Math.asin(-0) ); + +new TestCase( + "Infinity/Math.asin(-0)", + -Infinity, + Infinity/Math.asin(-0) ); + +new TestCase( + "Math.asin(1)", + Math.PI/2, + Math.asin(1) ); + +new TestCase( + "Math.asin(-1)", + -Math.PI/2, + Math.asin(-1) ); + +new TestCase( + "Math.asin(Math.SQRT1_2))", + Math.PI/4, + Math.asin(Math.SQRT1_2) ); + +new TestCase( + "Math.asin(-Math.SQRT1_2))", + -Math.PI/4, + Math.asin(-Math.SQRT1_2)); + +test(); diff --git a/js/src/tests/non262/Math/15.8.2.4.js b/js/src/tests/non262/Math/15.8.2.4.js new file mode 100644 index 0000000000..ee957aa93e --- /dev/null +++ b/js/src/tests/non262/Math/15.8.2.4.js @@ -0,0 +1,121 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + File Name: 15.8.2.4.js + ECMA Section: 15.8.2.4 atan( x ) + Description: return an approximation to the arc tangent of the + argument. the result is expressed in radians and + range is from -PI/2 to +PI/2. special cases: + - if x is NaN, the result is NaN + - if x == +0, the result is +0 + - if x == -0, the result is -0 + - if x == +Infinity, the result is approximately +PI/2 + - if x == -Infinity, the result is approximately -PI/2 + Author: christine@netscape.com + Date: 7 july 1997 + +*/ + +var SECTION = "15.8.2.4"; +var TITLE = "Math.atan()"; +var BUGNUMBER="77391"; + +printBugNumber(BUGNUMBER); + +writeHeaderToLog( SECTION + " "+ TITLE); + +new TestCase( + "Math.atan.length", + 1, + Math.atan.length ); + +new TestCase( + "Math.atan()", + Number.NaN, + Math.atan() ); + +new TestCase( + "Math.atan(void 0)", + Number.NaN, + Math.atan(void 0) ); + +new TestCase( + "Math.atan(null)", + 0, + Math.atan(null) ); + +new TestCase( + "Math.atan(NaN)", + Number.NaN, + Math.atan(Number.NaN) ); + +new TestCase( + "Math.atan('a string')", + Number.NaN, + Math.atan("a string") ); + +new TestCase( + "Math.atan('0')", + 0, + Math.atan('0') ); + +new TestCase( + "Math.atan('1')", + Math.PI/4, + Math.atan('1') ); + +new TestCase( + "Math.atan('-1')", + -Math.PI/4, + Math.atan('-1') ); + +new TestCase( + "Math.atan('Infinity)", + Math.PI/2, + Math.atan('Infinity') ); + +new TestCase( + "Math.atan('-Infinity)", + -Math.PI/2, + Math.atan('-Infinity') ); + +new TestCase( + "Math.atan(0)", + 0, + Math.atan(0) ); + +new TestCase( + "Math.atan(-0)", + -0, + Math.atan(-0) ); + +new TestCase( + "Infinity/Math.atan(-0)", + -Infinity, + Infinity/Math.atan(-0) ); + +new TestCase( + "Math.atan(Infinity)", + Math.PI/2, + Math.atan(Number.POSITIVE_INFINITY) ); + +new TestCase( + "Math.atan(-Infinity)", + -Math.PI/2, + Math.atan(Number.NEGATIVE_INFINITY) ); + +new TestCase( + "Math.atan(1)", + Math.PI/4, + Math.atan(1) ); + +new TestCase( + "Math.atan(-1)", + -Math.PI/4, + Math.atan(-1) ); + +test(); diff --git a/js/src/tests/non262/Math/15.8.2.5.js b/js/src/tests/non262/Math/15.8.2.5.js new file mode 100644 index 0000000000..0f1cf7182e --- /dev/null +++ b/js/src/tests/non262/Math/15.8.2.5.js @@ -0,0 +1,209 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + File Name: 15.8.2.5.js + ECMA Section: 15.8.2.5 atan2( y, x ) + Description: + + Author: christine@netscape.com + Date: 7 july 1997 + +*/ +var SECTION = "15.8.2.5"; +var TITLE = "Math.atan2(x,y)"; +var BUGNUMBER="76111"; + +printBugNumber(BUGNUMBER); + +writeHeaderToLog( SECTION + " "+ TITLE); + +new TestCase( + "Math.atan2.length", + 2, + Math.atan2.length ); + +new TestCase( + "Math.atan2(NaN, 0)", + Number.NaN, + Math.atan2(Number.NaN,0) ); + +new TestCase( + "Math.atan2(null, null)", + 0, + Math.atan2(null, null) ); + +new TestCase( + "Math.atan2(void 0, void 0)", + Number.NaN, + Math.atan2(void 0, void 0) ); + +new TestCase( + "Math.atan2()", + Number.NaN, + Math.atan2() ); + +new TestCase( + "Math.atan2(0, NaN)", + Number.NaN, + Math.atan2(0,Number.NaN) ); + +new TestCase( + "Math.atan2(1, 0)", + Math.PI/2, + Math.atan2(1,0) ); + +new TestCase( + "Math.atan2(1,-0)", + Math.PI/2, + Math.atan2(1,-0) ); + +new TestCase( + "Math.atan2(0,0.001)", + 0, + Math.atan2(0,0.001) ); + +new TestCase( + "Math.atan2(0,0)", + 0, + Math.atan2(0,0) ); + +new TestCase( + "Math.atan2(0, -0)", + Math.PI, + Math.atan2(0,-0) ); + +new TestCase( + "Math.atan2(0, -1)", + Math.PI, + Math.atan2(0, -1) ); + +new TestCase( + "Math.atan2(-0, 1)", + -0, + Math.atan2(-0, 1) ); + +new TestCase( + "Infinity/Math.atan2(-0, 1)", + -Infinity, + Infinity/Math.atan2(-0,1) ); + +new TestCase( + "Math.atan2(-0, 0)", + -0, + Math.atan2(-0,0) ); + +new TestCase( + "Math.atan2(-0, -0)", + -Math.PI, + Math.atan2(-0, -0) ); + +new TestCase( + "Math.atan2(-0, -1)", + -Math.PI, + Math.atan2(-0, -1) ); + +new TestCase( + "Math.atan2(-1, 0)", + -Math.PI/2, + Math.atan2(-1, 0) ); + +new TestCase( + "Math.atan2(-1, -0)", + -Math.PI/2, + Math.atan2(-1, -0) ); + +new TestCase( + "Math.atan2(1, Infinity)", + 0, + Math.atan2(1, Number.POSITIVE_INFINITY) ); + +new TestCase( + "Math.atan2(1,-Infinity)", + Math.PI, + Math.atan2(1, Number.NEGATIVE_INFINITY) ); + +new TestCase( + "Math.atan2(-1, Infinity)", + -0, + Math.atan2(-1,Number.POSITIVE_INFINITY) ); + +new TestCase( + "Infinity/Math.atan2(-1, Infinity)", + -Infinity, + Infinity/Math.atan2(-1,Infinity) ); + +new TestCase( + "Math.atan2(-1,-Infinity)", + -Math.PI, + Math.atan2(-1,Number.NEGATIVE_INFINITY) ); + +new TestCase( + "Math.atan2(Infinity, 0)", + Math.PI/2, + Math.atan2(Number.POSITIVE_INFINITY, 0) ); + +new TestCase( + "Math.atan2(Infinity, 1)", + Math.PI/2, + Math.atan2(Number.POSITIVE_INFINITY, 1) ); + +new TestCase( + "Math.atan2(Infinity,-1)", + Math.PI/2, + Math.atan2(Number.POSITIVE_INFINITY,-1) ); + +new TestCase( + "Math.atan2(Infinity,-0)", + Math.PI/2, + Math.atan2(Number.POSITIVE_INFINITY,-0) ); + +new TestCase( + "Math.atan2(-Infinity, 0)", + -Math.PI/2, + Math.atan2(Number.NEGATIVE_INFINITY, 0) ); + +new TestCase( + "Math.atan2(-Infinity,-0)", + -Math.PI/2, + Math.atan2(Number.NEGATIVE_INFINITY,-0) ); + +new TestCase( + "Math.atan2(-Infinity, 1)", + -Math.PI/2, + Math.atan2(Number.NEGATIVE_INFINITY, 1) ); + +new TestCase( + "Math.atan2(-Infinity, -1)", + -Math.PI/2, + Math.atan2(Number.NEGATIVE_INFINITY,-1) ); + +new TestCase( + "Math.atan2(Infinity, Infinity)", + Math.PI/4, + Math.atan2(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY) ); + +new TestCase( + "Math.atan2(Infinity, -Infinity)", + 3*Math.PI/4, + Math.atan2(Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY) ); + +new TestCase( + "Math.atan2(-Infinity, Infinity)", + -Math.PI/4, + Math.atan2(Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY) ); + +new TestCase( + "Math.atan2(-Infinity, -Infinity)", + -3*Math.PI/4, + Math.atan2(Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY) ); + +new TestCase( + "Math.atan2(-1, 1)", + -Math.PI/4, + Math.atan2( -1, 1) ); + +test(); diff --git a/js/src/tests/non262/Math/15.8.2.7.js b/js/src/tests/non262/Math/15.8.2.7.js new file mode 100644 index 0000000000..70af7e679f --- /dev/null +++ b/js/src/tests/non262/Math/15.8.2.7.js @@ -0,0 +1,247 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + File Name: 15.8.2.7.js + ECMA Section: 15.8.2.7 cos( x ) + Description: return an approximation to the cosine of the + argument. argument is expressed in radians + Author: christine@netscape.com + Date: 7 july 1997 + +*/ + +var SECTION = "15.8.2.7"; +var TITLE = "Math.cos(x)"; + +writeHeaderToLog( SECTION + " "+ TITLE); + +new TestCase( + "Math.cos.length", + 1, + Math.cos.length ); + +new TestCase( + "Math.cos()", + Number.NaN, + Math.cos() ); + +new TestCase( + "Math.cos(void 0)", + Number.NaN, + Math.cos(void 0) ); + +new TestCase( + "Math.cos(false)", + 1, + Math.cos(false) ); + +new TestCase( + "Math.cos(null)", + 1, + Math.cos(null) ); + +new TestCase( + "Math.cos('0')", + 1, + Math.cos('0') ); + +new TestCase( + "Math.cos('Infinity')", + Number.NaN, + Math.cos("Infinity") ); + +new TestCase( + "Math.cos('3.14159265359')", + -1, + Math.cos('3.14159265359') ); + +new TestCase( + "Math.cos(NaN)", + Number.NaN, + Math.cos(Number.NaN) ); + +new TestCase( + "Math.cos(0)", + 1, + Math.cos(0) ); + +new TestCase( + "Math.cos(-0)", + 1, + Math.cos(-0) ); + +new TestCase( + "Math.cos(Infinity)", + Number.NaN, + Math.cos(Number.POSITIVE_INFINITY) ); + +new TestCase( + "Math.cos(-Infinity)", + Number.NaN, + Math.cos(Number.NEGATIVE_INFINITY) ); + +new TestCase( + "Math.cos(0.7853981633974)", + 0.7071067811865, + Math.cos(0.7853981633974) ); + +new TestCase( + "Math.cos(1.570796326795)", + 0, + Math.cos(1.570796326795) ); + +new TestCase( + "Math.cos(2.356194490192)", + -0.7071067811865, + Math.cos(2.356194490192) ); + +new TestCase( + "Math.cos(3.14159265359)", + -1, + Math.cos(3.14159265359) ); + +new TestCase( + "Math.cos(3.926990816987)", + -0.7071067811865, + Math.cos(3.926990816987) ); + +new TestCase( + "Math.cos(4.712388980385)", + 0, + Math.cos(4.712388980385) ); + +new TestCase( + "Math.cos(5.497787143782)", + 0.7071067811865, + Math.cos(5.497787143782) ); + +new TestCase( + "Math.cos(Math.PI*2)", + 1, + Math.cos(Math.PI*2) ); + +new TestCase( + "Math.cos(Math.PI/4)", + Math.SQRT2/2, + Math.cos(Math.PI/4) ); + +new TestCase( + "Math.cos(Math.PI/2)", + 0, + Math.cos(Math.PI/2) ); + +new TestCase( + "Math.cos(3*Math.PI/4)", + -Math.SQRT2/2, + Math.cos(3*Math.PI/4) ); + +new TestCase( + "Math.cos(Math.PI)", + -1, + Math.cos(Math.PI) ); + +new TestCase( + "Math.cos(5*Math.PI/4)", + -Math.SQRT2/2, + Math.cos(5*Math.PI/4) ); + +new TestCase( + "Math.cos(3*Math.PI/2)", + 0, + Math.cos(3*Math.PI/2) ); + +new TestCase( + "Math.cos(7*Math.PI/4)", + Math.SQRT2/2, + Math.cos(7*Math.PI/4) ); + +new TestCase( + "Math.cos(Math.PI*2)", + 1, + Math.cos(2*Math.PI) ); + +new TestCase( + "Math.cos(-0.7853981633974)", + 0.7071067811865, + Math.cos(-0.7853981633974) ); + +new TestCase( + "Math.cos(-1.570796326795)", + 0, + Math.cos(-1.570796326795) ); + +new TestCase( + "Math.cos(-2.3561944901920)", + -.7071067811865, + Math.cos(2.3561944901920) ); + +new TestCase( + "Math.cos(-3.14159265359)", + -1, + Math.cos(3.14159265359) ); + +new TestCase( + "Math.cos(-3.926990816987)", + -0.7071067811865, + Math.cos(3.926990816987) ); + +new TestCase( + "Math.cos(-4.712388980385)", + 0, + Math.cos(4.712388980385) ); + +new TestCase( + "Math.cos(-5.497787143782)", + 0.7071067811865, + Math.cos(5.497787143782) ); + +new TestCase( + "Math.cos(-6.28318530718)", + 1, + Math.cos(6.28318530718) ); + +new TestCase( + "Math.cos(-Math.PI/4)", + Math.SQRT2/2, + Math.cos(-Math.PI/4) ); + +new TestCase( + "Math.cos(-Math.PI/2)", + 0, + Math.cos(-Math.PI/2) ); + +new TestCase( + "Math.cos(-3*Math.PI/4)", + -Math.SQRT2/2, + Math.cos(-3*Math.PI/4) ); + +new TestCase( + "Math.cos(-Math.PI)", + -1, + Math.cos(-Math.PI) ); + +new TestCase( + "Math.cos(-5*Math.PI/4)", + -Math.SQRT2/2, + Math.cos(-5*Math.PI/4) ); + +new TestCase( + "Math.cos(-3*Math.PI/2)", + 0, + Math.cos(-3*Math.PI/2) ); + +new TestCase( + "Math.cos(-7*Math.PI/4)", + Math.SQRT2/2, + Math.cos(-7*Math.PI/4) ); + +new TestCase( + "Math.cos(-Math.PI*2)", + 1, + Math.cos(-Math.PI*2) ); + +test(); diff --git a/js/src/tests/non262/Math/15.8.2.8.js b/js/src/tests/non262/Math/15.8.2.8.js new file mode 100644 index 0000000000..78f7eb7898 --- /dev/null +++ b/js/src/tests/non262/Math/15.8.2.8.js @@ -0,0 +1,84 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + File Name: 15.8.2.8.js + ECMA Section: 15.8.2.8 Math.exp(x) + Description: return an approximation to the exponential function of + the argument (e raised to the power of the argument) + special cases: + - if x is NaN return NaN + - if x is 0 return 1 + - if x is -0 return 1 + - if x is Infinity return Infinity + - if x is -Infinity return 0 + Author: christine@netscape.com + Date: 7 july 1997 +*/ + + +var SECTION = "15.8.2.8"; +var TITLE = "Math.exp(x)"; + +writeHeaderToLog( SECTION + " "+ TITLE); + +new TestCase( "Math.exp.length", + 1, + Math.exp.length ); + +new TestCase( "Math.exp()", + Number.NaN, + Math.exp() ); + +new TestCase( "Math.exp(null)", + 1, + Math.exp(null) ); + +new TestCase( "Math.exp(void 0)", + Number.NaN, + Math.exp(void 0) ); + +new TestCase( "Math.exp(1)", + Math.E, + Math.exp(1) ); + +new TestCase( "Math.exp(true)", + Math.E, + Math.exp(true) ); + +new TestCase( "Math.exp(false)", + 1, + Math.exp(false) ); + +new TestCase( "Math.exp('1')", + Math.E, + Math.exp('1') ); + +new TestCase( "Math.exp('0')", + 1, + Math.exp('0') ); + +new TestCase( "Math.exp(NaN)", + Number.NaN, + Math.exp(Number.NaN) ); + +new TestCase( "Math.exp(0)", + 1, + Math.exp(0) ); + +new TestCase( "Math.exp(-0)", + 1, + Math.exp(-0) ); + +new TestCase( "Math.exp(Infinity)", + Number.POSITIVE_INFINITY, + Math.exp(Number.POSITIVE_INFINITY) ); + +new TestCase( "Math.exp(-Infinity)", + 0, + Math.exp(Number.NEGATIVE_INFINITY) ); + +test(); diff --git a/js/src/tests/non262/Math/20.2.2.ToNumber.js b/js/src/tests/non262/Math/20.2.2.ToNumber.js new file mode 100644 index 0000000000..de1f4e612c --- /dev/null +++ b/js/src/tests/non262/Math/20.2.2.ToNumber.js @@ -0,0 +1,112 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +/* + * ECMA-262 6th Edition / Draft November 8, 2013 + * + * 20.2.2 Function Properties of the Math Object + */ + +/* + * This custom object will allow us to check if valueOf() is called + */ + +TestNumber.prototype = new Number(); + +function TestNumber(value) { + this.value = value; + this.valueOfCalled = false; +} + +TestNumber.prototype = { + valueOf: function() { + this.valueOfCalled = true; + return this.value; + } +} + +// Verify that each TestNumber's flag is set after calling Math func +function test(func /*, args */) { + var args = Array.prototype.slice.call(arguments, 1); + func.apply(null, args); + + for (var i = 0; i < args.length; ++i) + assertEq(args[i].valueOfCalled, true); +} + +// Note that we are not testing these functions' return values +// We only test whether valueOf() is called for each argument + +// 1. Test Math.atan2() +var x = new TestNumber(1); +test(Math.atan2, x); + +var x = new TestNumber(1); +var y = new TestNumber(2); +test(Math.atan2, y, x); + +// Remove comment block once patch for bug 896264 is approved +/* +// 2. Test Math.hypot() +var x = new TestNumber(1); +test(Math.hypot, x); + +var x = new TestNumber(1); +var y = new TestNumber(2); +test(Math.hypot, x, y); + +var x = new TestNumber(1); +var y = new TestNumber(2); +var z = new TestNumber(3); +test(Math.hypot, x, y, z); +*/ + +// Remove comment block once patch for bug 808148 is approved +/* +// 3. Test Math.imul() +var x = new TestNumber(1); +test(Math.imul, x); + +var x = new TestNumber(1); +var y = new TestNumber(2); +test(Math.imul, x, y); +*/ + +// 4. Test Math.max() +var x = new TestNumber(1); +test(Math.max, x); + +var x = new TestNumber(1); +var y = new TestNumber(2); +test(Math.max, x, y); + +var x = new TestNumber(1); +var y = new TestNumber(2); +var z = new TestNumber(3); +test(Math.max, x, y, z); + +// 5. Test Math.min() +var x = new TestNumber(1); +test(Math.min, x); + +var x = new TestNumber(1); +var y = new TestNumber(2); +test(Math.min, x, y); + +var x = new TestNumber(1); +var y = new TestNumber(2); +var z = new TestNumber(3); +test(Math.min, x, y, z); + +// 6. Test Math.pow() +var x = new TestNumber(1); +test(Math.pow, x); + +var x = new TestNumber(1); +var y = new TestNumber(2); +test(Math.pow, x, y); + +reportCompare(0, 0, "ok"); + diff --git a/js/src/tests/non262/Math/Pow.js b/js/src/tests/non262/Math/Pow.js new file mode 100644 index 0000000000..281c716a76 --- /dev/null +++ b/js/src/tests/non262/Math/Pow.js @@ -0,0 +1,117 @@ +// |reftest| skip-if(!xulRuntime.shell) +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 1135708; +var summary = "Implement the exponentiation operator"; + +print(BUGNUMBER + ": " + summary); + +// Constant folding +assertEq(2 ** 2 ** 3, 256); +assertEq(1 ** 1 ** 4, 1); + +// No folding +var two = 2; +var three = 3; +var four = 4; +assertEq(two ** two ** three, 256); +assertEq(1 ** 1 ** four, 1); + +// Operator precedence +assertEq(2 ** 3 / 2 ** 3, 1); +assertEq(2 ** 3 * 2 ** 3, 64); +assertEq(2 ** 3 + 2 ** 3, 16); + +// With parentheses +assertEq((2 ** 3) ** 2, 64); +assertEq(2 ** (3 ** 2), 512); + +// Assignment operator +var x = 2; +assertEq(x **= 2 ** 3, 256); +assertEq(x, 256); + +// Loop to test baseline and ION +for (var i=0; i<10000; i++) { + assertEq((2 ** 3) ** 2, 64); + assertEq(2 ** (3 ** 2), 512); + var x = 2; + assertEq(x **= 2 ** 3, 256); + assertEq(x, 256); +} + +// Comments should not be confused with exp operator +var a, c, e; +a = c = e = 2; +assertEq(a**/**b**/c/**/**/**d**/e, 16); + +// Two stars separated should not parse as exp operator +assertThrowsInstanceOf(function() { return Reflect.parse("2 * * 3"); }, SyntaxError); + +// Left-hand side expression must not be a unary expression. +for (let unaryOp of ["delete", "typeof", "void", "+", "-", "!", "~"]) { + assertThrowsInstanceOf(() => eval(unaryOp + " a ** 2"), SyntaxError); + assertThrowsInstanceOf(() => eval(unaryOp + " " + unaryOp + " a ** 2"), SyntaxError); +} + +// Test the other |delete| operators (DELETENAME and DELETEEXPR are already tested above). +assertThrowsInstanceOf(() => eval("delete a.name ** 2"), SyntaxError); +assertThrowsInstanceOf(() => eval("delete a[0] ** 2"), SyntaxError); + +// Unary expression lhs is valid if parenthesized. +for (let unaryOp of ["delete", "void", "+", "-", "!", "~"]) { + let a = 0; + eval("(" + unaryOp + " a) ** 2"); + eval("(" + unaryOp + " " + unaryOp + " a) ** 2"); +} +{ + let a = {}; + (delete a.name) ** 2; + (delete a[0]) ** 2; +} + +// Check if error propagation works +var thrower = { + get value() { + throw new Error(); + } +}; + +assertThrowsInstanceOf(function() { return thrower.value ** 2; }, Error); +assertThrowsInstanceOf(function() { return 2 ** thrower.value; }, Error); +assertThrowsInstanceOf(function() { return 2 ** thrower.value ** 2; }, Error); + +var convertibleToPrimitive = { + valueOf: function() { + throw new Error("oops"); + } +}; + +assertThrowsInstanceOf(function() { return convertibleToPrimitive ** 3; }, Error); +assertThrowsInstanceOf(function() { return 3 ** convertibleToPrimitive; }, Error); + +assertEq(NaN ** 2, NaN); +assertEq(2 ** NaN, NaN); +assertEq(2 ** "3", 8); +assertEq("2" ** 3, 8); + +// Reflect.parse generates a correct parse tree for simplest case +var parseTree = Reflect.parse("a ** b"); +assertEq(parseTree.body[0].type, "ExpressionStatement"); +assertEq(parseTree.body[0].expression.operator, "**"); +assertEq(parseTree.body[0].expression.left.name, "a"); +assertEq(parseTree.body[0].expression.right.name, "b"); + +// Reflect.parse generates a tree following the right-associativity rule +var parseTree = Reflect.parse("a ** b ** c"); +assertEq(parseTree.body[0].type, "ExpressionStatement"); +assertEq(parseTree.body[0].expression.left.name, "a"); +assertEq(parseTree.body[0].expression.right.operator, "**"); +assertEq(parseTree.body[0].expression.right.left.name, "b"); +assertEq(parseTree.body[0].expression.right.right.name, "c"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Math/acosh-approx.js b/js/src/tests/non262/Math/acosh-approx.js new file mode 100644 index 0000000000..3854a5909d --- /dev/null +++ b/js/src/tests/non262/Math/acosh-approx.js @@ -0,0 +1,283 @@ +var cosh_data = [ + [1.0000014305114746, 0.0016914556651292944], + [1.0000019073486328, 0.001953124689559275], + [1.000007152557373, 0.003782208044661295], + [1.000013828277588, 0.005258943946801101], + [1.0000171661376953, 0.005859366618129203], + [1.0000600814819336, 0.010961831992188852], + [1.0001168251037598, 0.015285472131830425], + [1.0001487731933594, 0.017249319093529877], + [1.0003981590270996, 0.028218171738655373], + [1.000638484954834, 0.03573281468231457], + [1.0010714530944824, 0.046287402472878776], + [1.0030217170715332, 0.07771996527168971], + [1.0049939155578613, 0.0998975930860278], + [1.0092840194702148, 0.13615938768032465], + [1.024169921875, 0.21942279004958354], + [1.0622773170471191, 0.3511165938166055], + [1.1223440170288086, 0.48975026711288183], + [1.2495574951171875, 0.692556883708491], + [1.4912219047546387, 0.954530572221414], + [1.9838471412658691, 1.307581416910453], + [2.1576128005981445, 1.4035188779741334], + [2.406397819519043, 1.5250070845427517], + [3.386958122253418, 1.8905372013072799], + [4.451677322387695, 2.1735673399948254], + [6.9391326904296875, 2.625091127868242], + [7.756023406982422, 2.737434918695162], + [8.882369995117188, 2.8740317167801948], + [9.869171142578125, 2.97998639328949], + [16.848876953125, 3.516549380542481], + [16.88458251953125, 3.51867003468025], + [18.18859100341797, 3.593185165198829], + [18.82012176513672, 3.6273672142963385], + [19.184181213378906, 3.646553244410946], + [24.039520263671875, 3.872413451393967], + [26.556991577148438, 3.972085568933329], + [27.921104431152344, 4.022209178119238], + [32.314666748046875, 4.168428891496629], + [34.73008728027344, 4.240546229861005], + [36.51556396484375, 4.290698214968891], + [38.851287841796875, 4.352722738491574], + [49.46875, 4.594386162629449], + [49.67265319824219, 4.598500387004538], + [55.821014404296875, 4.7152173401856095], + [57.119781494140625, 4.73822104001982], + [60.37983703613281, 4.793733825338029], + [63.4661865234375, 4.8435923769530165], + [63.822418212890625, 4.849190310904695], + [64.36642456054688, 4.85767897228448], + [65.82318115234375, 4.880061548144127], + [68.60302734375, 4.921430721025434], + [70.173583984375, 4.94406835208057], + [71.80126953125, 4.967000841791218], + [75.40786743164062, 5.016014824864732], + [75.49771118164062, 5.017205657609766], + [78.06475830078125, 5.0506448716550825], + [79.64892578125, 5.0707363201405276], + [79.8707275390625, 5.073517411135063], + [82.14324951171875, 5.101574796209937], + [86.42214965820312, 5.152357710985635], + [87.75869750976562, 5.167705692500117], + [94.24942016601562, 5.2390637098028074], + [95.00259399414062, 5.247023676519904], + [96.06402587890625, 5.258134994273664], + [99.10101318359375, 5.289261389093961], + [104.82595825195312, 5.345425863147171], + [105.89431762695312, 5.3555664787245885], + [106.750244140625, 5.363617180711895], + [109.40167236328125, 5.388152468690488], + [111.29598999023438, 5.405320225963013], + [112.68215942382812, 5.417698597745429], + [115.84786987304688, 5.445406415908933], + [122.51895141601562, 5.501396249028249], + [126.29083251953125, 5.531718947357248], + [127.88677978515625, 5.544277233951787], + [128.29241943359375, 5.547444176085567], + [129.49658203125, 5.556786759298988], + [138.73651123046875, 5.625710723366437], + [139.18450927734375, 5.628934733085022], + [139.9705810546875, 5.634566685055491], + [143.6336669921875, 5.660401141376928], + [149.2176513671875, 5.698541939965668], + [150.61602783203125, 5.7078698961812995], + [151.65460205078125, 5.714741890601693], + [154.77532958984375, 5.735111323217677], + [158.9586181640625, 5.761781191641161], + [159.23260498046875, 5.763503378028959], + [166.89166259765625, 5.810483079631769], + [169.22418212890625, 5.824362807770767], + [170.85247802734375, 5.833939098607025], + [175.641845703125, 5.861586030831371], + [176.47808837890625, 5.866335876872544], + [177.0284423828125, 5.869449614294116], + [178.81622314453125, 5.879497954012966], + [181.28570556640625, 5.893213844044451], + [190.84246826171875, 5.944588630523773], + [191.39764404296875, 5.947493525920713], + [194.2606201171875, 5.962341215900494], + [194.89630126953125, 5.9656082276276], + [196.72125244140625, 5.9749284849312865], + [196.76788330078125, 5.975165500176202], + [198.0592041015625, 5.981706804024238], + [199.97052001953125, 5.991310884439669], + [202.70001220703125, 6.004868209578554], + [204.95684814453125, 6.0159406892865155], + [206.92059326171875, 6.025476453825986], + [211.4588623046875, 6.047172064627678], + [211.6217041015625, 6.0479418642231595], + [212.15936279296875, 6.050479329955437], + [219.93341064453125, 6.086466833749719], + [223.34747314453125, 6.101870903204913], + [228.56036376953125, 6.1249427443985525], + [229.53656005859375, 6.129204755426344], + [231.15753173828125, 6.136241935513706], + [235.22589111328125, 6.153688953514383], + [237.17108154296875, 6.1619244798633215], + [237.904541015625, 6.165012268502458], + [243.202392578125, 6.187036941752032], + [244.296875, 6.191527178125454], + [245.39239501953125, 6.196001570568187], + [245.80389404296875, 6.197677082130341], + [249.68365478515625, 6.2133379061260285], + [252.32763671875, 6.223871642756905], + [253.4725341796875, 6.228398760115369], + [264.1583251953125, 6.269692237869835], + [265.867919921875, 6.276143287577458], + [273.893798828125, 6.305884283737176], + [274.060546875, 6.306492908028797], + [274.06298828125, 6.3065018163217115], + [275.31201171875, 6.31104892482331], + [281.2171630859375, 6.3322712125431915], + [284.3428955078125, 6.343324976847916], + [284.8428955078125, 6.345081883725142], + [287.3035888671875, 6.353683609448096], + [290.8973388671875, 6.366114643735997], + [293.0467529296875, 6.373476431987165], + [293.048583984375, 6.3734826803404045], + [296.819091796875, 6.3862671775996915], + [297.6572265625, 6.389086936901673], + [308.40625, 6.424562459508495], + [316.5472412109375, 6.4506171773701535], + [320.2418212890625, 6.462221144761522], + [322.33642578125, 6.468740575092418], + [323.5101318359375, 6.472375224718483], + [327.8939208984375, 6.485834999462654], + [328.0833740234375, 6.486412623146554], + [328.214599609375, 6.486812521370483], + [332.13916015625, 6.498698952535687], + [339.6888427734375, 6.521175044233963], + [340.171630859375, 6.522595306993373], + [340.22998046875, 6.522766822935215], + [340.9984130859375, 6.52502285413445], + [347.719482421875, 6.5445411825986985], + [347.921142578125, 6.5451209675856825], + [349.8392333984375, 6.55061885367159], + [353.1812744140625, 6.560126626713879], + [353.3170166015625, 6.560510895819139], + [354.9730224609375, 6.565186990039135], + [355.6412353515625, 6.567067660815945], + [363.193603515625, 6.588081320423386], + [363.7503662109375, 6.5896131163651415], + [366.66650390625, 6.597598047275183], + [370.5828857421875, 6.608222493065004], + [371.822998046875, 6.611563301604297], + [375.8822021484375, 6.622421213257873], + [377.1107177734375, 6.625684248051368], + [377.588623046875, 6.626950731244344], + [378.8428955078125, 6.630267034079059], + [379.1123046875, 6.630977920761718], + [381.1038818359375, 6.636217452968849], + [382.1112060546875, 6.638857149899159], + [382.9927978515625, 6.641161660644278], + [387.1845703125, 6.652047018118426], + [389.669921875, 6.658445560711748], + [389.804443359375, 6.658790721334144], + [396.3114013671875, 6.675345858154136], + [397.005126953125, 6.677094789236718], + [397.1934814453125, 6.6775691166680895], + [397.8046875, 6.679106750673113], + [398.8426513671875, 6.681712590609845], + [399.1663818359375, 6.682523938576487], + [399.2547607421875, 6.68274532345516], + [400.33984375, 6.685459416477178], + [403.9578857421875, 6.694456277839498], + [404.279541015625, 6.6952522228540765], + [405.0574951171875, 6.6971746771142415], + [407.328125, 6.702764738337774], + [407.547119140625, 6.7033022311799595], + [410.5994873046875, 6.710763953621196], + [410.8016357421875, 6.711256159037373], + [411.129638671875, 6.712054288828399], + [411.9053955078125, 6.713939407502346], + [415.5833740234375, 6.722828986708716], + [417.669189453125, 6.727835453862132], + [420.517822265625, 6.734632628835641], + [424.3853759765625, 6.743787740494532], + [424.7154541015625, 6.744565219553757], + [436.3419189453125, 6.7715720212680655], + [438.501953125, 6.776510146304201], + [439.3369140625, 6.778412462065226], + [445.5606689453125, 6.79247934060035], + [452.9901123046875, 6.809016260337229], + [453.77490234375, 6.810747231716348], + [456.7745361328125, 6.817335895109251], + [457.9520263671875, 6.819910421197311], + [458.6795654296875, 6.821497844004013], + [460.5164794921875, 6.8254946428721475], + [461.8717041015625, 6.828433164406687], + [464.7025146484375, 6.834543470287694], + [467.0626220703125, 6.839609377592375], + [467.0712890625, 6.839627933844213], + [470.096923828125, 6.846084943645239], + [475.1607666015625, 6.856799276049143], + [477.5537109375, 6.861822721577315], + [478.626220703125, 6.864066049482581], + [478.7958984375, 6.864420497333681], + [479.6864013671875, 6.866278653973069], + [479.7867431640625, 6.866487814627139], + [479.9122314453125, 6.8667493311188395], + [482.4793701171875, 6.872084270243208], + [482.5181884765625, 6.872164723177875], + [483.8797607421875, 6.874982560453874], + [484.4649658203125, 6.876191234145179], + [485.3258056640625, 6.877966548833207], + [490.57373046875, 6.888721726428236], + [493.7423095703125, 6.89515989558997], + [494.272216796875, 6.896232568812718], + [496.44775390625, 6.900624415355815], + [497.0401611328125, 6.901816998553275], + [498.234130859375, 6.9042162822876465], + [665.0791015625, 7.193052598670793], + [1170.29150390625, 7.758155143419732], + [2058.7958984375, 8.323023697145112], + [5824.533203125, 9.36298131161099], + [9114.30859375, 9.810748008110926], + [31388.40625, 11.047341056314202], + [53732.765625, 11.584925435512535], + [117455.09375, 12.366958539207397], + [246210.625, 13.107089828327874], + [513670.125, 13.84248373881162], + [788353.25, 14.27084873575108], + [1736171, 15.060339852215408], + [3770530, 15.835873313657556], + [4344090, 15.977474039173265], + [11419360, 16.943967899150145], + [31023240, 17.943394339560967], + [40665424, 18.214035936745432], + [129788064, 19.374560581709215], + [225668224, 19.927723623778547], + [450631936, 20.619308638400597], + [750941952, 21.129986093026698], + [1887358976, 22.05159150215413], + [3738011648, 22.734966842639743], + [7486695424, 23.42954051928097], + [12668080128, 23.955498471391667], + [23918272512, 24.591055724582848], + [48862560256, 25.305424481799395], + [113763549184, 26.150535181949436], + [161334755328, 26.499894449532565], + [321933279232, 27.19075733422632], + [715734122496, 27.989721778208146], + [1875817529344, 28.953212876533797] +]; + +var sloppy_tolerance = 8; // FIXME + +for (var [x, y] of cosh_data) + assertNear(Math.acosh(x), y, sloppy_tolerance); + +assertNear(Math.acosh(1e300), 691.4686750787737, sloppy_tolerance); +assertNear(Math.acosh(1.0000000001), 0.000014142136208675862, sloppy_tolerance); + +for (var i = 0; i <= 100; i++) { + var x = (i - 50) / 5; + var y = Math.cosh(x); + var z = Math.acosh(y); + assertNear(z, Math.abs(x), sloppy_tolerance); +} + +for (var i = 1; i < 20; i++) + assertNear(Math.acosh(Math.cosh(i)), i, sloppy_tolerance); + +reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Math/acosh-exact.js b/js/src/tests/non262/Math/acosh-exact.js new file mode 100644 index 0000000000..ededaa48e1 --- /dev/null +++ b/js/src/tests/non262/Math/acosh-exact.js @@ -0,0 +1,26 @@ +// Properties of Math.acosh that are guaranteed by the spec. + +// If x is NaN, the result is NaN. +assertEq(Math.acosh(NaN), NaN); + +// If x is less than 1, the result is NaN. +assertEq(Math.acosh(ONE_MINUS_EPSILON), NaN); +assertEq(Math.acosh(Number.MIN_VALUE), NaN); +assertEq(Math.acosh(+0), NaN); +assertEq(Math.acosh(-0), NaN); +assertEq(Math.acosh(-Number.MIN_VALUE), NaN); +assertEq(Math.acosh(-1), NaN); +assertEq(Math.acosh(-Number.MAX_VALUE), NaN); +assertEq(Math.acosh(-Infinity), NaN); + +for (var i = -20; i < 1; i++) + assertEq(Math.acosh(i), NaN); + +// If x is 1, the result is +0. +assertEq(Math.acosh(1), +0); + +// If x is +∞, the result is +∞. +assertEq(Math.acosh(Number.POSITIVE_INFINITY), Number.POSITIVE_INFINITY); + + +reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Math/asinh-approx.js b/js/src/tests/non262/Math/asinh-approx.js new file mode 100644 index 0000000000..354454fb40 --- /dev/null +++ b/js/src/tests/non262/Math/asinh-approx.js @@ -0,0 +1,303 @@ +var sinh_data = [ + [-497.181640625, -6.902103625349695], + [-495.216552734375, -6.898143347143859], + [-488.0980224609375, -6.883664481302669], + [-486.4609375, -6.880304842490273], + [-482.2261962890625, -6.871561546509046], + [-468.167236328125, -6.841973895837549], + [-465.553955078125, -6.836376331805493], + [-464.288330078125, -6.833654100575195], + [-463.558837890625, -6.8320816635009045], + [-453.82861328125, -6.8108680173663085], + [-448.7835693359375, -6.799689165151487], + [-446.0499267578125, -6.793579326246197], + [-432.4046630859375, -6.762510387544996], + [-424.145751953125, -6.743225720989222], + [-402.8682861328125, -6.691758395994307], + [-402.4595947265625, -6.690743430063694], + [-390.1383056640625, -6.6596501292114505], + [-387.5355224609375, -6.652956360641761], + [-381.0023193359375, -6.635954365364267], + [-374.8172607421875, -6.619587562578274], + [-374.1033935546875, -6.617681179427804], + [-373.01318359375, -6.614762741096185], + [-370.0938720703125, -6.60690568753706], + [-364.5230712890625, -6.591738907156094], + [-361.3756103515625, -6.583066984213974], + [-358.1136474609375, -6.573999516974134], + [-350.8861083984375, -6.553610904389896], + [-350.7060546875, -6.553097634736138], + [-345.5616455078125, -6.538320325468202], + [-342.386962890625, -6.529090881007076], + [-341.9425048828125, -6.527791927233787], + [-337.3883056640625, -6.514383886150781], + [-328.8133544921875, -6.488639771044976], + [-326.1348876953125, -6.480460592697477], + [-313.12744140625, -6.439759999015992], + [-311.6180419921875, -6.434927968512049], + [-303.40478515625, -6.4082177348965725], + [-291.9320068359375, -6.369671035834965], + [-289.791015625, -6.362310184909175], + [-288.07568359375, -6.356373428913315], + [-282.76220703125, -6.337756593913614], + [-278.9659423828125, -6.32424009706147], + [-276.1881103515625, -6.314232650754295], + [-269.843994140625, -6.290994606392703], + [-256.47509765625, -6.240182555852785], + [-248.91619873046875, -6.2102675039793604], + [-245.71783447265625, -6.197335184435549], + [-244.9049072265625, -6.194021350132335], + [-242.49176025390625, -6.184119163536406], + [-223.97491455078125, -6.104686221071835], + [-223.0770263671875, -6.100669325836893], + [-221.50177001953125, -6.093582856519022], + [-214.1610107421875, -6.0598807500687935], + [-202.9705810546875, -6.0062142965262515], + [-200.1683349609375, -5.9923121073369945], + [-198.0869140625, -5.981859446096083], + [-191.8330078125, -5.9497792165852905], + [-183.4495849609375, -5.90509449745879], + [-182.9005126953125, -5.902097012275789], + [-167.5517578125, -5.8144483910067954], + [-162.87738037109375, -5.786154254111214], + [-159.6142578125, -5.765917008989405], + [-150.01629638671875, -5.703902219845274], + [-148.34051513671875, -5.6926689504460395], + [-147.23760986328125, -5.685206387751923], + [-143.65484619140625, -5.660572815631807], + [-138.70599365234375, -5.625516713960633], + [-119.55416870117188, -5.476934234171879], + [-118.44155883789062, -5.467584665632571], + [-112.7041015625, -5.417932675603434], + [-111.43020629882812, -5.406565756574079], + [-107.77297973632812, -5.373195678988387], + [-107.6795654296875, -5.3723285712183735], + [-105.091796875, -5.348004040102253], + [-101.261474609375, -5.31087758970896], + [-95.79150390625, -5.255348419702703], + [-91.26885986328125, -5.206986845736275], + [-87.33349609375, -5.162914035396619], + [-78.23873901367188, -5.052952927749896], + [-77.912353515625, -5.048772883924985], + [-76.83489990234375, -5.034848487644809], + [-61.255645751953125, -4.808269821238499], + [-54.41380310058594, -4.689849459883311], + [-43.967193603515625, -4.476720236388958], + [-42.01084899902344, -4.431216695067421], + [-30.609375, -4.114720236218123], + [-26.711166381835938, -3.9785790831656023], + [-25.241317749023438, -3.9220215830953484], + [-14.624359130859375, -3.3770026324620295], + [-12.431087493896484, -3.214961448471211], + [-10.235607147216797, -3.021397455139021], + [-9.41094970703125, -2.937831931335705], + [-1.635939121246338, -1.267878515574959], + [1.6504814008555524e-12, 1.6504814008555524e-12], + [2.0654207510961697e-12, 2.0654207510961697e-12], + [6.933230031758164e-12, 6.933230031758164e-12], + [1.3351444949627478e-11, 1.3351444949627478e-11], + [1.6399812063916386e-11, 1.6399812063916386e-11], + [5.730159402528301e-11, 5.730159402528301e-11], + [1.113731329382972e-10, 1.113731329382972e-10], + [1.4214707189097453e-10, 1.4214707189097453e-10], + [3.8006320313144215e-10, 3.8006320313144215e-10], + [6.09162720266454e-10, 6.09162720266454e-10], + [1.0221641311147778e-9, 1.0221641311147778e-9], + [2.8819222563924995e-9, 2.8819222563924995e-9], + [4.7627768395841485e-9, 4.7627768395841485e-9], + [8.854133426439148e-9, 8.854133426439148e-9], + [2.3050326092288742e-8, 2.305032609228874e-8], + [5.9392490925347374e-8, 5.939249092534734e-8], + [1.166764889148908e-7, 1.1667648891489053e-7], + [2.3799674409019644e-7, 2.379967440901942e-7], + [4.684659415943315e-7, 4.6846594159431437e-7], + [9.382699772686465e-7, 9.382699772685088e-7], + [0.00000110398559627356, 0.0000011039855962733358], + [0.0000032917760108830407, 0.000003291776010877096], + [0.00000751721381675452, 0.000007517213816683722], + [0.000015114666894078255, 0.000015114666893502755], + [0.00002986399340443313, 0.00002986399339999406], + [0.00003387028118595481, 0.000033870281179478836], + [0.00009066011989489198, 0.00009066011977069884], + [0.00021949532674625516, 0.00021949532498377364], + [0.00043952150736004114, 0.00043952149320897676], + [0.0006333151832222939, 0.0006333151408864353], + [0.001115123275667429, 0.0011151230445582744], + [0.001962467096745968, 0.0019624658370807177], + [0.005553754046559334, 0.005553725496786973], + [0.008691128343343735, 0.008691018931968294], + [0.02993336319923401, 0.02992889492062484], + [0.05124260485172272, 0.05122020579778827], + [0.11201295256614685, 0.1117800293787828], + [0.23480379581451416, 0.23269806521543376], + [0.4898730516433716, 0.4721357117742938], + [0.7518312931060791, 0.694611571189336], + [1.655740737915039, 1.2781607348262256], + [3.5958566665649414, 1.9917262343245115], + [3.662705421447754, 2.009484184971722], + [4.142845153808594, 2.128787712416205], + [5.957065582275391, 2.4846967934155475], + [10.890350341796875, 3.083125584533294], + [27.3714599609375, 4.002981567623351], + [29.58606719970703, 4.080736210902826], + [30.79753875732422, 4.120845430011113], + [38.78157043457031, 4.351258506393416], + [46.88148498535156, 4.540883728536112], + [47.21551513671875, 4.547981853382592], + [47.2205810546875, 4.5480891170767], + [49.72361755371094, 4.599728302509061], + [61.557464599609375, 4.8131842711857535], + [67.82162475585938, 4.910082619934558], + [68.82363891601562, 4.924747230639767], + [73.75466918945312, 4.993937439635391], + [80.95669555664062, 5.087099712053554], + [85.26406860351562, 5.1389346970196295], + [85.2677001953125, 5.138977285472121], + [92.8238525390625, 5.223879832616765], + [94.50357055664062, 5.241812789460327], + [116.044677734375, 5.447141014648796], + [123.77554321289062, 5.511633288238573], + [132.3592529296875, 5.578681289305598], + [139.7633056640625, 5.633110296634631], + [143.9609375, 5.662701238627725], + [146.31298828125, 5.678906941005323], + [155.0980224609375, 5.737214893086866], + [155.47784423828125, 5.739660763047893], + [155.74066162109375, 5.741349685869528], + [163.60546875, 5.790614371552514], + [178.735107421875, 5.879059869096351], + [179.70269775390625, 5.884458728291027], + [179.81976318359375, 5.885109945587401], + [181.3594970703125, 5.893636014368936], + [194.82861328125, 5.965274032538233], + [195.23284912109375, 5.967346683696556], + [199.07666015625, 5.986843466070591], + [205.77423095703125, 6.019932686217942], + [206.04608154296875, 6.021252909681261], + [209.36480712890625, 6.037231102920489], + [210.703857421875, 6.043606439928324], + [215.2139892578125, 6.06478541011501], + [225.83892822265625, 6.112974120371601], + [226.95465087890625, 6.117902255760311], + [232.79864501953125, 6.1433256889594094], + [240.647216796875, 6.176483527820343], + [243.1324462890625, 6.186757751007361], + [251.26702880859375, 6.219667373726848], + [253.72906494140625, 6.229418088083555], + [254.6866455078125, 6.233184983047428], + [257.2001953125, 6.243005711460192], + [257.7401123046875, 6.245102704489327], + [261.731201171875, 6.260468857392134], + [263.75, 6.268152459140511], + [265.5167236328125, 6.2748285545831655], + [273.9171142578125, 6.305976070434008], + [278.897705078125, 6.32399546069982], + [279.167236328125, 6.324961403980197], + [292.207275390625, 6.370613506132747], + [293.5975341796875, 6.375359978930309], + [293.9749755859375, 6.3766447200146], + [295.1998291015625, 6.380802563199264], + [297.2799072265625, 6.387824152942429], + [297.9285888671875, 6.390003820200831], + [298.1058349609375, 6.3905985680679], + [300.2803955078125, 6.397866642974941], + [307.531005859375, 6.421725738171608], + [308.1754150390625, 6.423818963102848], + [309.7344970703125, 6.428865255911759], + [314.2847900390625, 6.443449261058927], + [314.7236328125, 6.444844602076255], + [320.8406982421875, 6.464094341970107], + [321.2459716796875, 6.465356699668166], + [321.9031982421875, 6.467400466944125], + [323.457763671875, 6.472218114936839], + [330.82861328125, 6.4947499213823265], + [335.008544921875, 6.507305446835735], + [340.7171630859375, 6.524202033435675], + [348.4677734375, 6.546694993078936], + [349.1292724609375, 6.548591493378012], + [372.4288330078125, 6.613194950203132], + [376.7574462890625, 6.6247505436339065], + [378.4306640625, 6.629181796246806], + [390.9031982421875, 6.6616087711302185], + [405.7918701171875, 6.698989091751707], + [407.3646240234375, 6.702857353572475], + [413.3758544921875, 6.717505881986416], + [415.7354736328125, 6.723197804327891], + [417.193603515625, 6.726699007993023], + [420.874755859375, 6.735483889307782], + [429.2635498046875, 6.755219602793124], + [429.756103515625, 6.756366380816258], + [433.9931640625, 6.766177290841293], + [434.0106201171875, 6.766217511883346], + [440.073974609375, 6.780091308338912], + [450.2220458984375, 6.802889310303153], + [455.017578125, 6.813484439494547], + [457.1668701171875, 6.818196843455478], + [457.5068359375, 6.818940201487998], + [459.2913818359375, 6.822833193143805], + [459.492431640625, 6.82327083544577], + [459.743896484375, 6.823817951018], + [464.888427734375, 6.834945773756887], + [464.96630859375, 6.835113285253827], + [467.6949462890625, 6.840964582694129], + [468.86767578125, 6.84346890521034], + [470.5927734375, 6.847141429556457], + [481.109619140625, 6.869243403190376], + [487.4595947265625, 6.882355637062964], + [488.521484375, 6.884531678915821], + [492.8812255859375, 6.89341643293734], + [494.0684814453125, 6.895822338701104], + [496.4613037109375, 6.900653737167637], + [716.154052734375, 7.2670429692740965], + [1799.92578125, 8.188647968122073], + [3564.845703125, 8.872023251113289], + [7139.869140625, 9.566596912986167], + [12081.22265625, 10.092554861905608], + [22810.2421875, 10.728112113864427], + [46598.96875, 11.442480870715618], + [108493.375, 12.28759157077177], + [153860.8125, 12.636950838344218], + [307019.5, 13.327813723030063], + [682577.25, 14.126778167009777], + [1788919, 15.090269265334971], + [3769169, 15.835512291283944], + [4327820, 15.973721689554742], + [11044024, 16.910547205715446], + [21423208, 17.573132558903225], + [62828288, 18.649063156437965], + [70207360, 18.760110887365155], + [154231424, 19.547111966180875], + [294509056, 20.193967491567523], + [1070557184, 21.484592263156223], + [1957922816, 22.088297141021556], + [3912507392, 22.780591462699917], + [7279233024, 23.401438520318692], + [9665245184, 23.684949498080787], + [22627590144, 24.5355829820426], + [60601991168, 25.520740767599584], + [134018236416, 26.31438890085422], + [204864946176, 26.73876398039979], + [284346286080, 27.06660583008718], + [914576637952, 28.234874284944635], + [1581915832320, 28.78280496108106] +]; + +for (var [x, y] of sinh_data) + assertNear(Math.asinh(x), y); + +assertNear(Math.asinh(1e300), 691.4686750787737); +assertNear(Math.asinh(1e-300), 1e-300); +assertNear(Math.asinh(1e-5), 0.000009999999999833334); +assertNear(Math.asinh(0.3), 0.29567304756342244); +assertNear(Math.asinh(1), 0.881373587019543); + +for (var i = 0; i <= 80; i++) { + var x = (i - 40) / 4; + assertNear(Math.asinh(Math.sinh(x)), x); +} + +for (var i = -20; i < 20; i++) + assertNear(Math.asinh(Math.sinh(i)), i); + +reportCompare(0, 0, "ok"); + diff --git a/js/src/tests/non262/Math/asinh-exact.js b/js/src/tests/non262/Math/asinh-exact.js new file mode 100644 index 0000000000..49463d01fc --- /dev/null +++ b/js/src/tests/non262/Math/asinh-exact.js @@ -0,0 +1,19 @@ +// Properties of Math.asinh that are guaranteed by the spec. + +// If x is NaN, the result is NaN. +assertEq(Math.asinh(NaN), NaN); + +// If x is +0, the result is +0. +assertEq(Math.asinh(+0), +0); + +// If x is −0, the result is −0. +assertEq(Math.asinh(-0), -0); + +// If x is +∞, the result is +∞. +assertEq(Math.asinh(Infinity), Infinity); + +// If x is −∞, the result is −∞. +assertEq(Math.asinh(-Infinity), -Infinity); + + +reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Math/atanh-approx.js b/js/src/tests/non262/Math/atanh-approx.js new file mode 100644 index 0000000000..fcf61892db --- /dev/null +++ b/js/src/tests/non262/Math/atanh-approx.js @@ -0,0 +1,280 @@ +var tanh_data = [ + [-0.9999983310699463, -6.998237084679027], + [-0.9999978542327881, -6.87257975132917], + [-0.999992847442627, -6.2705920974657525], + [-0.9999861717224121, -5.940967614084813], + [-0.9999828338623047, -5.832855225378502], + [-0.9999399185180664, -5.20646301208756], + [-0.9998834133148193, -4.8749821841810785], + [-0.9998509883880615, -4.752279497280338], + [-0.9996016025543213, -4.260504202858904], + [-0.9993612766265869, -4.0244334353203115], + [-0.9989283084869385, -3.7655641082999236], + [-0.9969782829284668, -3.246782610980921], + [-0.9950058460235596, -2.9950671179940938], + [-0.9942638874053955, -2.9256242749609536], + [-0.990715742111206, -2.6839646283308363], + [-0.9903340339660645, -2.663723350226518], + [-0.9760982990264893, -2.207464998348322], + [-0.975830078125, -2.201817459680556], + [-0.9728245735168457, -2.1424542308291437], + [-0.9643559455871582, -2.0046686756020917], + [-0.9377224445343018, -1.7188337346177065], + [-0.9362406730651855, -1.7066940482565154], + [-0.9310147762298584, -1.6659543005533146], + [-0.9284839630126953, -1.6472838718760747], + [-0.9270248413085938, -1.6368067340881562], + [-0.9075665473937988, -1.5135473477311114], + [-0.897477388381958, -1.4590986086331497], + [-0.8920106887817383, -1.431681573516303], + [-0.8776559829711914, -1.365471286049011], + [-0.864722728729248, -1.3117705583444539], + [-0.8482067584991455, -1.249725893334944], + [-0.8056559562683105, -1.1145246028592257], + [-0.8048388957977295, -1.112200609756455], + [-0.7801985740661621, -1.0458778330822556], + [-0.7749934196472168, -1.032711173436253], + [-0.7619285583496094, -1.0007967281362184], + [-0.7504425048828125, -0.9739672824457072], + [-0.7495596408843994, -0.9719492983286864], + [-0.7481319904327393, -0.968698942014487], + [-0.7459518909454346, -0.9637657636705832], + [-0.7401137351989746, -0.9507308314464193], + [-0.7289731502532959, -0.9265325319867653], + [-0.7226788997650146, -0.9132299082876396], + [-0.7161557674407959, -0.8997082193533088], + [-0.7017018795013428, -0.8706453720344796], + [-0.7013418674468994, -0.86993650130945], + [-0.691054105758667, -0.8499705913361888], + [-0.6847054958343506, -0.837919455842005], + [-0.6838164329528809, -0.8362476144993315], + [-0.6747090816497803, -0.8193374156276964], + [-0.6575610637664795, -0.7885046044142132], + [-0.6522045135498047, -0.7791255597799839], + [-0.6261923313140869, -0.7351275788820003], + [-0.623173713684082, -0.7301771459970386], + [-0.6067488193511963, -0.7037597526130627], + [-0.5838055610656738, -0.6682166303197608], + [-0.579524040222168, -0.6617457665293066], + [-0.5760939121246338, -0.656596458857398], + [-0.5654678344726562, -0.6408350116350283], + [-0.5578761100769043, -0.6297442839791668], + [-0.5523209571838379, -0.6217149641475687], + [-0.5396339893341064, -0.6036390747171698], + [-0.5128989219665527, -0.5666556256064771], + [-0.5087778568267822, -0.5610793900942042], + [-0.4977825880050659, -0.546353950571504], + [-0.4913865327835083, -0.5378865967606703], + [-0.48976075649261475, -0.5357455496477738], + [-0.48493504524230957, -0.5294166456244711], + [-0.4479050636291504, -0.4820764946679979], + [-0.4461095333099365, -0.4798325976916711], + [-0.4429593086242676, -0.47590653371561276], + [-0.42827916145324707, -0.45778739362936793], + [-0.40590059757232666, -0.4306933608076879], + [-0.40029656887054443, -0.4240020382545707], + [-0.3961341381072998, -0.4190551379319939], + [-0.3836275339126587, -0.40430627175908734], + [-0.36686253547668457, -0.3847928551425507], + [-0.3657644987106323, -0.38352464227459343], + [-0.33507001399993896, -0.3485286317501442], + [-0.32572221755981445, -0.3380352468276522], + [-0.3191967010498047, -0.3307524237890151], + [-0.3000025749206543, -0.3095224337886503], + [-0.29665136337280273, -0.3058438250228025], + [-0.2944457530975342, -0.3034271164344305], + [-0.2872810363769531, -0.29560018347246825], + [-0.27738428115844727, -0.28484608203169437], + [-0.2390844225883484, -0.2438028008332661], + [-0.23685944080352783, -0.24144425169391517], + [-0.2253856658935547, -0.2293228153248168], + [-0.22283810377120972, -0.22664053064745143], + [-0.21552443504333496, -0.21895773601143995], + [-0.2153375744819641, -0.21876178107952995], + [-0.21016258001327515, -0.21334143320771737], + [-0.20250272750854492, -0.2053409277979887], + [-0.19156384468078613, -0.19396008474133075], + [-0.18251943588256836, -0.18458771439322938], + [-0.17464947700500488, -0.17645844608618066], + [-0.15646183490753174, -0.15775766677189154], + [-0.15580910444259644, -0.15708862621964176], + [-0.15365445613861084, -0.15488112515549593], + [-0.122499018907547, -0.12311733609904851], + [-0.1088167130947113, -0.10924929296737837], + [-0.08792558312416077, -0.08815322150790302], + [-0.08401328325271606, -0.08421178632314608], + [-0.06121261417865753, -0.06128924075509796], + [-0.05341699719429016, -0.05346789060550386], + [-0.05047759413719177, -0.05052053189238029], + [-0.02924579381942749, -0.029254136237332657], + [-0.02485968917608261, -0.02486481220617492], + [-0.020469173789024353, -0.02047203328100153], + [-0.01882001757621765, -0.018822240021756347], + [-0.016152501106262207, -0.016153906073109205], + [-0.0032715508714318275, -0.003271562543358962], + [1.6504814008555524e-12, 1.6504814008555524e-12], + [2.0654207510961697e-12, 2.0654207510961697e-12], + [6.933230031758164e-12, 6.933230031758164e-12], + [1.3351444949627478e-11, 1.3351444949627478e-11], + [1.6399812063916386e-11, 1.6399812063916386e-11], + [5.730159402528301e-11, 5.730159402528301e-11], + [1.113731329382972e-10, 1.113731329382972e-10], + [1.4214707189097453e-10, 1.4214707189097453e-10], + [3.8006320313144215e-10, 3.8006320313144215e-10], + [6.09162720266454e-10, 6.09162720266454e-10], + [1.0221641311147778e-9, 1.0221641311147778e-9], + [2.8819222563924995e-9, 2.8819222563924995e-9], + [4.7627768395841485e-9, 4.7627768395841485e-9], + [8.854133426439148e-9, 8.854133426439148e-9], + [2.3050326092288742e-8, 2.3050326092288745e-8], + [5.9392490925347374e-8, 5.939249092534745e-8], + [1.166764889148908e-7, 1.1667648891489133e-7], + [2.3799674409019644e-7, 2.3799674409020094e-7], + [4.684659415943315e-7, 4.684659415943658e-7], + [9.382699772686465e-7, 9.382699772689218e-7], + [0.00000110398559627356, 0.0000011039855962740086], + [0.0000032917760108830407, 0.0000032917760108949305], + [0.00000751721381675452, 0.000007517213816896115], + [0.000015114666894078255, 0.000015114666895229252], + [0.00002986399340443313, 0.00002986399341331128], + [0.00003387028118595481, 0.000033870281198906756], + [0.00009066011989489198, 0.00009066012014327826], + [0.00021949532674625516, 0.0002194953302712184], + [0.00043952150736004114, 0.0004395215356621756], + [0.0006333151832222939, 0.0006333152678940465], + [0.001115123275667429, 0.0011151237378863419], + [0.001962467096745968, 0.001962469616086656], + [0.005553754046559334, 0.005553811147953338], + [0.007324676960706711, 0.0073248079567425], + [0.008691128343343735, 0.008691347183450786], + [0.011912941932678223, 0.011913505535037906], + [0.02993336319923401, 0.029942308168570204], + [0.05124260485172272, 0.05128752666822782], + [0.05473744869232178, 0.05479221508125444], + [0.06158891320228577, 0.061666963819518306], + [0.09375360608100891, 0.09402975380882211], + [0.09442159533500671, 0.09470370926367391], + [0.09443172812461853, 0.09471393321406026], + [0.09943729639053345, 0.09976699249016487], + [0.11201295256614685, 0.11248498303558895], + [0.12310260534286499, 0.12373016402339168], + [0.13562965393066406, 0.13647060950861248], + [0.13763350248336792, 0.13851257866094746], + [0.14749455451965332, 0.14857829980464834], + [0.1618971824645996, 0.16333433166790448], + [0.17051106691360474, 0.17219298693637355], + [0.17051833868026733, 0.17220047646299907], + [0.18562912940979004, 0.18780647318150087], + [0.18898820877075195, 0.1912876932893582], + [0.23206615447998047, 0.23637212433914523], + [0.23480379581451416, 0.2392675448267427], + [0.2646920680999756, 0.27114729033023005], + [0.2794986963272095, 0.2871382059344433], + [0.28789305686950684, 0.2962673858386819], + [0.292596697807312, 0.30140373665239234], + [0.3101649284362793, 0.320727882769785], + [0.3109246492385864, 0.3215686893944558], + [0.31145012378692627, 0.3221505056451929], + [0.3271782398223877, 0.3396649461699478], + [0.3574345111846924, 0.37394153436545424], + [0.3593693971633911, 0.37616159223090223], + [0.35960352420806885, 0.37643046596933716], + [0.3626827001571655, 0.3799714809649667], + [0.38961827754974365, 0.4113499159905353], + [0.3904266357421875, 0.41230330080214], + [0.3981136083602905, 0.4214052375603139], + [0.411507248878479, 0.43742438709579096], + [0.4120509624481201, 0.43807911823743495], + [0.41868770122528076, 0.4460997186945703], + [0.42136549949645996, 0.4493511447897729], + [0.4516327381134033, 0.48674948990473677], + [0.4538639783859253, 0.4895560176112375], + [0.4655507802963257, 0.5043748446613433], + [0.48124635219573975, 0.5246050193978663], + [0.48621630668640137, 0.5310932154891663], + [0.4898730516433716, 0.5358932909903701], + [0.5024838447570801, 0.5526234425942533], + [0.5074074268341064, 0.5592320547729962], + [0.5093221664428711, 0.5618140818296767], + [0.5143489837646484, 0.5686253097655146], + [0.5154285430908203, 0.5700943191671631], + [0.5234100818634033, 0.5810250825991418], + [0.5274472236633301, 0.5866018515043636], + [0.5309803485870361, 0.5915094458340507], + [0.5477793216705322, 0.6152030999229688], + [0.5577394962310791, 0.6295459624918965], + [0.5582785606384277, 0.6303287742357745], + [0.5843560695648193, 0.6690521906099505], + [0.5871362686157227, 0.6732844960442398], + [0.5878911018371582, 0.6744372167164567], + [0.5903406143188477, 0.6781887236623534], + [0.5945003032684326, 0.684597775489552], + [0.5957975387573242, 0.6866065102131665], + [0.5961520671844482, 0.6871563252400655], + [0.6005008220672607, 0.6939300827887145], + [0.6150004863739014, 0.7169242329194352], + [0.6162893772125244, 0.7189998055497108], + [0.6194069385528564, 0.7240422748778544], + [0.6285066604614258, 0.7389438896054792], + [0.6293842792510986, 0.7403958734869583], + [0.6416172981262207, 0.7609178886018204], + [0.6424276828765869, 0.7622965466812235], + [0.6437420845031738, 0.7645378650643101], + [0.6468508243560791, 0.769864795178161], + [0.6615910530090332, 0.7956379107512945], + [0.669950008392334, 0.8106524185805045], + [0.6813662052154541, 0.8316597473423232], + [0.6968657970428467, 0.8611812790659296], + [0.6981887817382812, 0.8637579113749143], + [0.7447831630706787, 0.9611360201710216], + [0.7518312931060791, 0.9771540941752986], + [0.7534394264221191, 0.9808634133542229], + [0.7567856311798096, 0.9886489208209699], + [0.7817282676696777, 1.0497991719828956], + [0.8115026950836182, 1.1314141444187586], + [0.814647912979126, 1.1406947755584418], + [0.8266689777374268, 1.1775230833699681], + [0.8313877582550049, 1.1926138225701433], + [0.8343038558959961, 1.2021323323039612], + [0.8416652679443359, 1.2268570644335162], + [0.8584413528442383, 1.2873896671573652], + [0.8678996562957764, 1.3245040433929398], + [0.8679344654083252, 1.3246451309261607], + [0.8800599575042725, 1.3760334877782177], + [0.9003539085388184, 1.4740852961194106], + [0.9099440574645996, 1.5271990851861994], + [0.9142425060272217, 1.5527768948273004], + [0.9149219989776611, 1.556931837197936], + [0.9184908866882324, 1.5792896628381612], + [0.9188928604125977, 1.5818663359427627], + [0.919395923614502, 1.5851082843320008], + [0.9296839237213135, 1.6560555223295368], + [0.9298396110534668, 1.6572041418041492], + [0.9352962970733643, 1.6990986433619266], + [0.9376416206359863, 1.718164398807965], + [0.9410912990570068, 1.7475084077246632], + [0.962122917175293, 1.9737180163455101], + [0.9748215675354004, 2.1811227771083783], + [0.9769454002380371, 2.2257214499698255], + [0.985663890838623, 2.4654635601650536], + [0.9880380630493164, 2.5565869228142004], + [0.9928233623504639, 2.8132383539094192], + [1e-300, 1e-300], + [0.00001, 0.000010000000000333334], + [0.3, 0.3095196042031117], + [1e-30, 1e-30], + [1e-10, 1e-10], +]; + +var sloppy_tolerance = 2; // FIXME + +for (var [x, y] of tanh_data) + assertNear(Math.atanh(x), y, sloppy_tolerance); + +assertNear(Math.atanh(+3 / 5), +Math.log(2), sloppy_tolerance); +assertNear(Math.atanh(-3 / 5), -Math.log(2), sloppy_tolerance); + +for (var i = -1; i < 1; i += 0.05) + assertNear(Math.atanh(Math.tanh(i)), i, sloppy_tolerance); + +reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Math/atanh-exact.js b/js/src/tests/non262/Math/atanh-exact.js new file mode 100644 index 0000000000..f49bdb1ac4 --- /dev/null +++ b/js/src/tests/non262/Math/atanh-exact.js @@ -0,0 +1,35 @@ +// Properties of Math.atanh that are guaranteed by the spec. + +// If x is NaN, the result is NaN. +assertEq(Math.atanh(NaN), NaN); + +// If x is less than −1, the result is NaN. +assertEq(Math.atanh(-ONE_PLUS_EPSILON), NaN); +assertEq(Math.atanh(-Number.MAX_VALUE), NaN); +assertEq(Math.atanh(-Infinity), NaN); + +for (var i = -5; i < -1; i += 0.1) + assertEq(Math.atanh(i), NaN); + +// If x is greater than 1, the result is NaN. +assertEq(Math.atanh(ONE_PLUS_EPSILON), NaN); +assertEq(Math.atanh(Number.MAX_VALUE), NaN); +assertEq(Math.atanh(Infinity), NaN); + +for (var i = +5; i > +1; i -= 0.1) + assertEq(Math.atanh(i), NaN); + +// If x is −1, the result is −∞. +assertEq(Math.atanh(-1), -Infinity); + +// If x is +1, the result is +∞. +assertEq(Math.atanh(+1), Infinity); + +// If x is +0, the result is +0. +assertEq(Math.atanh(+0), +0); + +// If x is −0, the result is −0. +assertEq(Math.atanh(-0), -0); + + +reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Math/browser.js b/js/src/tests/non262/Math/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Math/cbrt-approx.js b/js/src/tests/non262/Math/cbrt-approx.js new file mode 100644 index 0000000000..1f54bb5a62 --- /dev/null +++ b/js/src/tests/non262/Math/cbrt-approx.js @@ -0,0 +1,17 @@ +assertEq(Math.cbrt(1), 1); +assertEq(Math.cbrt(-1), -1); + +assertNear(Math.cbrt(1e-300), 1e-100); +assertNear(Math.cbrt(-1e-300), -1e-100); + +var cbrt_data = [ + [ Math.E, 1.3956124250860895 ], + [ Math.PI, 1.4645918875615231 ], + [ Math.LN2, 0.8849970445005177 ], + [ Math.SQRT2, 1.1224620483093728 ] +]; + +for (var [x, y] of cbrt_data) + assertNear(Math.cbrt(x), y); + +reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Math/cbrt-exact.js b/js/src/tests/non262/Math/cbrt-exact.js new file mode 100644 index 0000000000..e0b7289f03 --- /dev/null +++ b/js/src/tests/non262/Math/cbrt-exact.js @@ -0,0 +1,19 @@ +// Properties of Math.cbrt that are guaranteed by the spec. + +// If x is NaN, the result is NaN. +assertEq(Math.cbrt(NaN), NaN); + +// If x is +0, the result is +0. +assertEq(Math.cbrt(+0), +0); + +// If x is −0, the result is −0. +assertEq(Math.cbrt(-0), -0); + +// If x is +∞, the result is +∞. +assertEq(Math.cbrt(Infinity), Infinity); + +// If x is −∞, the result is −∞. +assertEq(Math.cbrt(-Infinity), -Infinity); + + +reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Math/clz32.js b/js/src/tests/non262/Math/clz32.js new file mode 100644 index 0000000000..0062676365 --- /dev/null +++ b/js/src/tests/non262/Math/clz32.js @@ -0,0 +1,40 @@ +// Undefined and NaN end up as zero after ToUint32 +assertEq(Math.clz32(), 32); +assertEq(Math.clz32(NaN), 32); +assertEq(Math.clz32.call(), 32); +// 0 +assertEq(Math.clz32(null), 32); +assertEq(Math.clz32(false), 32); +// 1 +assertEq(Math.clz32(true), 31); +// 3 +assertEq(Math.clz32(3.5), 30); +// NaN -> 0 +assertEq(Math.clz32({}), 32); +// 2 +assertEq(Math.clz32({valueOf: function() { return 2; }}), 30); +// 0 -> 0 +assertEq(Math.clz32([]), 32); +assertEq(Math.clz32(""), 32); +// NaN -> 0 +assertEq(Math.clz32([1, 2, 3]), 32); +assertEq(Math.clz32("bar"), 32); +// 15 +assertEq(Math.clz32("15"), 28); + + +assertEq(Math.clz32(0x80000000), 0); +assertEq(Math.clz32(0xF0FF1000), 0); +assertEq(Math.clz32(0x7F8F0001), 1); +assertEq(Math.clz32(0x3FFF0100), 2); +assertEq(Math.clz32(0x1FF50010), 3); +assertEq(Math.clz32(0x00800000), 8); +assertEq(Math.clz32(0x00400000), 9); +assertEq(Math.clz32(0x00008000), 16); +assertEq(Math.clz32(0x00004000), 17); +assertEq(Math.clz32(0x00000080), 24); +assertEq(Math.clz32(0x00000040), 25); +assertEq(Math.clz32(0x00000001), 31); +assertEq(Math.clz32(0), 32); + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Math/cosh-approx.js b/js/src/tests/non262/Math/cosh-approx.js new file mode 100644 index 0000000000..d724aa2946 --- /dev/null +++ b/js/src/tests/non262/Math/cosh-approx.js @@ -0,0 +1,276 @@ +assertEq(Math.cosh(1000), Infinity); +assertEq(Math.cosh(Number.MAX_VALUE), Infinity); +assertNear(Math.cosh(1e-30), 1); +assertNear(Math.cosh(1e-10), 1); + +var cosh_data = [ + [0.0016914556651292944, 1.0000014305114746], + [0.001953124689559275, 1.0000019073486328], + [0.003782208044661295, 1.000007152557373], + [0.005258943946801101, 1.000013828277588], + [0.005859366618129203, 1.0000171661376953], + [0.010961831992188852, 1.0000600814819336], + [0.015285472131830425, 1.0001168251037598], + [0.017249319093529877, 1.0001487731933594], + [0.028218171738655373, 1.0003981590270996], + [0.03573281468231457, 1.000638484954834], + [0.046287402472878776, 1.0010714530944824], + [0.07771996527168971, 1.0030217170715332], + [0.0998975930860278, 1.0049939155578613], + [0.13615938768032465, 1.0092840194702148], + [0.21942279004958354, 1.024169921875], + [0.3511165938166055, 1.0622773170471191], + [0.48975026711288183, 1.1223440170288086], + [0.692556883708491, 1.2495574951171875], + [0.954530572221414, 1.4912219047546387], + [1.307581416910453, 1.983847141265869], + [1.4035188779741334, 2.1576128005981445], + [1.5250070845427517, 2.406397819519043], + [1.8905372013072799, 3.386958122253418], + [2.1735673399948254, 4.451677322387695], + [2.625091127868242, 6.939132690429686], + [2.737434918695162, 7.756023406982421], + [2.8740317167801948, 8.88236999511719], + [2.97998639328949, 9.869171142578123], + [3.516549380542481, 16.848876953125], + [3.51867003468025, 16.884582519531254], + [3.593185165198829, 18.18859100341797], + [3.6273672142963385, 18.82012176513672], + [3.646553244410946, 19.184181213378906], + [3.872413451393967, 24.03952026367187], + [3.972085568933329, 26.556991577148434], + [4.022209178119238, 27.921104431152337], + [4.168428891496629, 32.31466674804686], + [4.240546229861005, 34.730087280273445], + [4.290698214968891, 36.51556396484376], + [4.352722738491574, 38.851287841796875], + [4.594386162629449, 49.46875], + [4.598500387004538, 49.67265319824219], + [4.7152173401856095, 55.821014404296896], + [4.73822104001982, 57.119781494140604], + [4.793733825338029, 60.37983703613279], + [4.8435923769530165, 63.46618652343747], + [4.849190310904695, 63.82241821289062], + [4.85767897228448, 64.36642456054685], + [4.880061548144127, 65.82318115234375], + [4.921430721025434, 68.60302734374997], + [4.94406835208057, 70.17358398437497], + [4.967000841791218, 71.80126953124997], + [5.016014824864732, 75.40786743164065], + [5.017205657609766, 75.49771118164062], + [5.0506448716550825, 78.06475830078126], + [5.0707363201405276, 79.64892578125], + [5.073517411135063, 79.87072753906253], + [5.101574796209937, 82.14324951171874], + [5.152357710985635, 86.4221496582031], + [5.167705692500117, 87.75869750976562], + [5.2390637098028074, 94.24942016601562], + [5.247023676519904, 95.00259399414062], + [5.258134994273664, 96.06402587890626], + [5.289261389093961, 99.10101318359374], + [5.345425863147171, 104.82595825195315], + [5.3555664787245885, 105.89431762695308], + [5.363617180711895, 106.750244140625], + [5.388152468690488, 109.40167236328122], + [5.405320225963013, 111.2959899902344], + [5.417698597745429, 112.68215942382815], + [5.445406415908933, 115.8478698730469], + [5.501396249028249, 122.51895141601562], + [5.531718947357248, 126.29083251953128], + [5.544277233951787, 127.88677978515626], + [5.547444176085567, 128.29241943359372], + [5.556786759298988, 129.49658203125006], + [5.625710723366437, 138.7365112304687], + [5.628934733085022, 139.18450927734378], + [5.634566685055491, 139.97058105468747], + [5.660401141376928, 143.63366699218747], + [5.698541939965668, 149.21765136718753], + [5.7078698961812995, 150.6160278320313], + [5.714741890601693, 151.6546020507813], + [5.735111323217677, 154.77532958984378], + [5.761781191641161, 158.95861816406253], + [5.763503378028959, 159.23260498046878], + [5.810483079631769, 166.89166259765622], + [5.824362807770767, 169.22418212890625], + [5.833939098607025, 170.85247802734372], + [5.861586030831371, 175.64184570312503], + [5.866335876872544, 176.47808837890625], + [5.869449614294116, 177.02844238281247], + [5.879497954012966, 178.81622314453122], + [5.893213844044451, 181.28570556640625], + [5.944588630523773, 190.84246826171866], + [5.947493525920713, 191.39764404296875], + [5.962341215900494, 194.26062011718753], + [5.9656082276276, 194.89630126953122], + [5.9749284849312865, 196.7212524414062], + [5.975165500176202, 196.76788330078128], + [5.981706804024238, 198.05920410156241], + [5.991310884439669, 199.9705200195312], + [6.004868209578554, 202.70001220703122], + [6.0159406892865155, 204.95684814453116], + [6.025476453825986, 206.92059326171866], + [6.047172064627678, 211.45886230468741], + [6.0479418642231595, 211.62170410156256], + [6.050479329955437, 212.1593627929687], + [6.086466833749719, 219.93341064453125], + [6.101870903204913, 223.3474731445312], + [6.1249427443985525, 228.56036376953128], + [6.129204755426344, 229.53656005859375], + [6.136241935513706, 231.1575317382813], + [6.153688953514383, 235.22589111328134], + [6.1619244798633215, 237.17108154296884], + [6.165012268502458, 237.90454101562506], + [6.187036941752032, 243.202392578125], + [6.191527178125454, 244.29687500000003], + [6.196001570568187, 245.3923950195312], + [6.197677082130341, 245.80389404296875], + [6.2133379061260285, 249.68365478515622], + [6.223871642756905, 252.3276367187501], + [6.228398760115369, 253.47253417968756], + [6.269692237869835, 264.1583251953126], + [6.276143287577458, 265.8679199218749], + [6.305884283737176, 273.89379882812494], + [6.306492908028797, 274.0605468750001], + [6.3065018163217115, 274.06298828125006], + [6.31104892482331, 275.3120117187501], + [6.3322712125431915, 281.2171630859374], + [6.343324976847916, 284.34289550781244], + [6.345081883725142, 284.84289550781256], + [6.353683609448096, 287.30358886718756], + [6.366114643735997, 290.8973388671876], + [6.373476431987165, 293.0467529296875], + [6.3734826803404045, 293.04858398437494], + [6.3862671775996915, 296.819091796875], + [6.389086936901673, 297.6572265625], + [6.424562459508495, 308.4062500000001], + [6.4506171773701535, 316.5472412109376], + [6.462221144761522, 320.24182128906256], + [6.468740575092418, 322.33642578125], + [6.472375224718483, 323.5101318359374], + [6.485834999462654, 327.8939208984375], + [6.486412623146554, 328.08337402343744], + [6.486812521370483, 328.214599609375], + [6.498698952535687, 332.1391601562501], + [6.521175044233963, 339.6888427734376], + [6.522595306993373, 340.171630859375], + [6.522766822935215, 340.2299804687499], + [6.52502285413445, 340.99841308593744], + [6.5445411825986985, 347.7194824218749], + [6.5451209675856825, 347.9211425781249], + [6.55061885367159, 349.8392333984375], + [6.560126626713879, 353.1812744140626], + [6.560510895819139, 353.31701660156244], + [6.565186990039135, 354.97302246093756], + [6.567067660815945, 355.64123535156233], + [6.588081320423386, 363.19360351562517], + [6.5896131163651415, 363.7503662109376], + [6.597598047275183, 366.66650390624983], + [6.608222493065004, 370.5828857421874], + [6.611563301604297, 371.822998046875], + [6.622421213257873, 375.88220214843756], + [6.625684248051368, 377.11071777343744], + [6.626950731244344, 377.58862304687483], + [6.630267034079059, 378.8428955078124], + [6.630977920761718, 379.11230468749994], + [6.636217452968849, 381.10388183593756], + [6.638857149899159, 382.1112060546874], + [6.641161660644278, 382.9927978515625], + [6.652047018118426, 387.1845703124999], + [6.658445560711748, 389.66992187499994], + [6.658790721334144, 389.8044433593749], + [6.675345858154136, 396.3114013671875], + [6.677094789236718, 397.00512695312494], + [6.6775691166680895, 397.1934814453124], + [6.679106750673113, 397.80468749999994], + [6.681712590609845, 398.84265136718744], + [6.682523938576487, 399.16638183593744], + [6.68274532345516, 399.2547607421874], + [6.685459416477178, 400.3398437499999], + [6.694456277839498, 403.9578857421875], + [6.6952522228540765, 404.27954101562517], + [6.6971746771142415, 405.05749511718744], + [6.702764738337774, 407.328125], + [6.7033022311799595, 407.54711914062506], + [6.710763953621196, 410.59948730468756], + [6.711256159037373, 410.8016357421876], + [6.712054288828399, 411.12963867187494], + [6.713939407502346, 411.9053955078124], + [6.722828986708716, 415.5833740234374], + [6.727835453862132, 417.66918945312506], + [6.734632628835641, 420.51782226562506], + [6.743787740494532, 424.38537597656233], + [6.744565219553757, 424.71545410156244], + [6.7715720212680655, 436.3419189453125], + [6.776510146304201, 438.50195312500017], + [6.778412462065226, 439.33691406250017], + [6.79247934060035, 445.5606689453126], + [6.809016260337229, 452.9901123046875], + [6.810747231716348, 453.7749023437499], + [6.817335895109251, 456.7745361328125], + [6.819910421197311, 457.9520263671875], + [6.821497844004013, 458.6795654296874], + [6.8254946428721475, 460.51647949218767], + [6.828433164406687, 461.87170410156256], + [6.834543470287694, 464.70251464843756], + [6.839609377592375, 467.06262207031267], + [6.839627933844213, 467.0712890625001], + [6.846084943645239, 470.09692382812494], + [6.856799276049143, 475.16076660156233], + [6.861822721577315, 477.5537109374998], + [6.864066049482581, 478.62622070312517], + [6.864420497333681, 478.79589843750017], + [6.866278653973069, 479.68640136718733], + [6.866487814627139, 479.7867431640625], + [6.8667493311188395, 479.9122314453126], + [6.872084270243208, 482.4793701171875], + [6.872164723177875, 482.5181884765627], + [6.874982560453874, 483.87976074218767], + [6.876191234145179, 484.46496582031233], + [6.877966548833207, 485.3258056640624], + [6.888721726428236, 490.57373046875006], + [6.89515989558997, 493.74230957031244], + [6.896232568812718, 494.2722167968751], + [6.900624415355815, 496.44775390624983], + [6.901816998553275, 497.0401611328125], + [6.9042162822876465, 498.23413085937483], + [7.193052598670793, 665.0791015625001], + [7.758155143419732, 1170.29150390625], + [8.323023697145112, 2058.795898437501], + [9.36298131161099, 5824.533203125004], + [9.810748008110926, 9114.308593750004], + [11.047341056314202, 31388.40624999998], + [11.584925435512535, 53732.765624999956], + [12.366958539207397, 117455.0937500001], + [13.107089828327874, 246210.62499999983], + [13.84248373881162, 513670.1250000003], + [14.27084873575108, 788353.2499999999], + [15.060339852215408, 1736170.999999999], + [15.835873313657556, 3770530.0000000005], + [15.977474039173265, 4344089.999999998], + [16.943967899150145, 11419360.000000006], + [17.943394339560967, 31023239.99999997], + [18.214035936745432, 40665424.00000006], + [19.374560581709215, 129788063.99999991], + [19.927723623778547, 225668224.00000027], + [20.619308638400597, 450631936.0000006], + [21.129986093026698, 750941952.0000008], + [22.05159150215413, 1887358976.0000033], + [22.734966842639743, 3738011648.0000052], + [23.42954051928097, 7486695423.99999], + [23.955498471391667, 12668080127.99998], + [24.591055724582848, 23918272512], + [25.305424481799395, 48862560256.00005], + [26.150535181949436, 113763549183.99998], + [26.499894449532565, 161334755328.00018], + [27.19075733422632, 321933279232.0004], + [27.989721778208146, 715734122496], + [28.953212876533797, 1875817529343.9976], +]; + +for (var [x, y] of cosh_data) + assertNear(Math.cosh(x), y); + +for (var i = -20; i < 20; i++) + assertNear(Math.cosh(i), (Math.exp(i) + Math.exp(-i)) / 2); + +reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Math/cosh-exact.js b/js/src/tests/non262/Math/cosh-exact.js new file mode 100644 index 0000000000..a302776c4f --- /dev/null +++ b/js/src/tests/non262/Math/cosh-exact.js @@ -0,0 +1,19 @@ +// Properties of Math.cosh that are guaranteed by the spec. + +// If x is NaN, the result is NaN. +assertEq(Math.cosh(NaN), NaN); + +// If x is +0, the result is 1. +assertEq(Math.cosh(+0), 1); + +// If x is −0, the result is 1. +assertEq(Math.cosh(-0), 1); + +// If x is +∞, the result is +∞. +assertEq(Math.cosh(Infinity), Infinity); + +// If x is −∞, the result is +∞. +assertEq(Math.cosh(-Infinity), Infinity); + + +reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Math/exp-exact.js b/js/src/tests/non262/Math/exp-exact.js new file mode 100644 index 0000000000..e004f74718 --- /dev/null +++ b/js/src/tests/non262/Math/exp-exact.js @@ -0,0 +1,29 @@ +// Properties of Math.exp that are guaranteed by the spec. + +// If x is NaN, the result is NaN. +assertEq(Math.exp(NaN), NaN); + +// If x is +0, the result is 1. +assertEq(Math.exp(+0), 1); + +// If x is −0, the result is 1. +assertEq(Math.exp(-0), 1); + +// If x is +∞, the result is +∞. +assertEq(Math.exp(Infinity), Infinity); + +// If x is −∞, the result is +0. +assertEq(Math.exp(-Infinity), +0); + + +// Not guaranteed by the specification, but generally assumed to hold. + +// If x is 1, the result is Math.E. +assertEq(Math.exp(1), Math.E); + +// If x is -1, the result is 1/Math.E. +assertEq(Math.exp(-1), 1 / Math.E); + + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Math/expm1-approx.js b/js/src/tests/non262/Math/expm1-approx.js new file mode 100644 index 0000000000..397ab97ebf --- /dev/null +++ b/js/src/tests/non262/Math/expm1-approx.js @@ -0,0 +1,62 @@ +assertNear(Math.expm1(1e-300), 1e-300); +assertNear(Math.expm1(1e-100), 1e-100); +assertNear(Math.expm1(1e-14), 1.000000000000005e-14); +assertNear(Math.expm1(1e-6), 0.0000010000005000001665); + +var expm1_data = [ + [ -1.875817529344e-70, -1.875817529344e-70 ], + [ -7.09962844069878e-15, -7.099628440698755e-15 ], + [ -2.114990849122478e-10, -2.1149908488988187e-10 ], + [ -0.0000031404608812881633, -0.000003140455950046052 ], + + [ -0.0000011039855962733358, -0.0000011039849868814618 ], + [ -0.000015114666893502755, -0.0000151145526675006 ], + [ -0.000033870281179478836, -0.000033869707587981166 ], + [ -0.00043952149320897676, -0.00043942491778698985 ], + [ -0.005553725496786973, -0.005538332073473123 ], + [ -0.05122020579778827, -0.049930563302241604 ], + [ -0.4721357117742938, -0.3763311320344197 ], + [ -1.2781607348262256, -0.7214508446489242 ], + + [ 1.875817529344e-70, 1.875817529344e-70 ], + [ 6.261923313140869e-30, 6.261923313140869e-30 ], + [ 7.09962844069878e-15, 7.099628440698805e-15 ], + [ 1.3671879628418538e-12, 1.3671879628427884e-12 ], + [ 2.114990849122478e-10, 2.1149908493461373e-10 ], + [ 1.6900931765206906e-8, 1.6900931908027652e-8 ], + [ 0.0000031404608812881633, 0.0000031404658125405988 ], + + [ 0.0000011039855962733358, 0.0000011039862056656584 ], + [ 0.000015114666893502755, 0.000015114781120655907 ], + [ 0.000033870281179478836, 0.00003387085478392845 ], + [ 0.00043952149320897676, 0.0004396180969330924 ], + [ 0.005553725496786973, 0.005569176019645543 ], + [ 0.05122020579778827, 0.05255464640120383 ], + [ 0.4721357117742938, 0.6034149712523235 ], + [ 1.2781607348262256, 2.590030631181154 ], + + [ 3.0693960800487883, 20.528897017773147 ], + [ 5.560441648750136, 258.9376120972927 ], + [ 7.4227656046482595, 1672.6557833191303 ], + [ 11.378926299184645, 87458.07941992789 ], +]; + +for (var [x, y] of expm1_data) + assertNear(Math.expm1(x), y); + +var sloppy_tolerance = 34; + +var expm1_data_sloppy = [ + [ 20.11881628179155, 546375092.2355127 ], + [ 33.45034324980283, 336743709091858.2 ], + [ 46.43974518513109, 147409364838076710000 ], + [ 54.60105936314322, 5.163435870507142e+23 ], + [ 84.29619209850242, 4.067907545704549e+36 ], + [ 125.38131800315817, 2.8340959047812913e+54 ], + [ 216.85489905212918, 1.5096839294759775e+94 ], +]; + +for (var [x, y] of expm1_data_sloppy) + assertNear(Math.expm1(x), y, sloppy_tolerance); + +reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Math/expm1-exact.js b/js/src/tests/non262/Math/expm1-exact.js new file mode 100644 index 0000000000..57b94ed225 --- /dev/null +++ b/js/src/tests/non262/Math/expm1-exact.js @@ -0,0 +1,20 @@ +// Properties of Math.expm1 that are guaranteed by the spec. + +// If x is NaN, the result is NaN. +assertEq(Math.expm1(NaN), NaN); + +// If x is +0, the result is +0. +assertEq(Math.expm1(+0), +0); + +// If x is −0, the result is −0. +assertEq(Math.expm1(-0), -0); + +// If x is +∞, the result is +∞. +assertEq(Math.expm1(Infinity), Infinity); + +// If x is −∞, the result is -1. +assertEq(Math.expm1(-Infinity), -1); + + +reportCompare(0, 0, "ok"); + diff --git a/js/src/tests/non262/Math/expm1-monotonicity.js b/js/src/tests/non262/Math/expm1-monotonicity.js new file mode 100644 index 0000000000..2ae25708d1 --- /dev/null +++ b/js/src/tests/non262/Math/expm1-monotonicity.js @@ -0,0 +1,94 @@ +var BUGNUMBER = 897634; +var summary = "expm1 should be monotonically increasing"; + +print(BUGNUMBER + ": " + summary); + +function test(x, prev, next) { + assertEq(Math.expm1(prev) <= Math.expm1(x), true); + assertEq(Math.expm1(x) <= Math.expm1(next), true); +} + +// Thresholds in fdlibm expm1 implementation. + +// |hx| == 0x40862E42 or not +test(-709.7822265625, -709.7822265625001, -709.7822265624999); +test(709.7822265625, 709.7822265624999, 709.7822265625001); + +// |hx| == 0x4043687A or not +test(-38.81622314453125, -38.81622314453126, -38.81622314453124); +test(38.81622314453125, 38.81622314453124, 38.81622314453126); + +// |hx| == 0x7ff00000 or not +test(-1.7976931348623157e+308, -Infinity, -1.7976931348623155e+308); +test(1.7976931348623157e+308, 1.7976931348623155e+308, Infinity); + +// |hx| == 0x3fd62e42 or not +test(-0.3465733528137207, -0.34657335281372076, -0.34657335281372065); +test(0.3465733528137207, 0.34657335281372065, 0.34657335281372076); + +// |hx| == 0x3FF0A2B2 or not +test(-1.0397205352783203, -1.0397205352783205, -1.03972053527832); +test(1.0397205352783203, 1.03972053527832, 1.0397205352783205); + +// |hx| == 0x3c900000 or not +test(-5.551115123125783e-17, -5.551115123125784e-17, -5.551115123125782e-17); +test(5.551115123125783e-17, 5.551115123125782e-17, 5.551115123125784e-17); + +// x < -0.25 or not +test(-0.25, -0.25000000000000006, -0.24999999999999997); + +// k == -1 or k == -2 +test(-1.0397207708399179, -1.039720770839918, -1.0397207708399177); + +// k == -1 or k == 0 +test(-0.3465735912322998, -0.34657359123229986, -0.34657359123229975); + +// k == 0 or k == 1 +test(0.3465735912322998, 0.34657359123229975, 0.34657359123229986); + +// k == 1 or k == 2 +test(1.039720770839918, 1.0397207708399179, 1.0397207708399183); + +// k == 19 or k == 20 +test(13.516370020918933, 13.51637002091893, 13.516370020918934); + +// k == 56 or k == 57 +test(39.16281570163691, 39.1628157016369, 39.162815701636916); + +// k == 1023 or k == 1024 +test(709.436139303104, 709.4361393031039, 709.4361393031041); + +// k == 1024 or more +test(709.7827128933841, 709.782712893384, 709.7827128933842); + +// Some more random cases. +test(-1.7976931348623157e+308, -Infinity, -1.7976931348623155e+308); +test(-1e+223, -1.0000000000000002e+223, -9.999999999999999e+222); +test(-1e+100, -1.0000000000000002e+100, -9.999999999999998e+99); +test(-10000000000, -10000000000.000002, -9999999999.999998); +test(-100000, -100000.00000000001, -99999.99999999999); +test(-100, -100.00000000000001, -99.99999999999999); +test(-10, -10.000000000000002, -9.999999999999998); +test(-1, -1, -0.9999999999999999); +test(-0.01, -0.010000000000000002, -0.009999999999999998); +test(-0.00001, -0.000010000000000000003, -0.000009999999999999999); +test(-1e-10, -1.0000000000000002e-10, -9.999999999999999e-11); +test(-1e-100, -1.0000000000000001e-100, -9.999999999999999e-101); +test(-5e-324, -1e-323, 0); +test(0, -5e-324, 5e-324); +test(5e-324, 0, 1e-323); +test(1e-100, 9.999999999999999e-101, 1.0000000000000001e-100); +test(1e-10, 9.999999999999999e-11, 1.0000000000000002e-10); +test(0.00001, 0.000009999999999999999, 0.000010000000000000003); +test(0.01, 0.009999999999999998, 0.010000000000000002); +test(1, 0.9999999999999999, 1); +test(10, 9.999999999999998, 10.000000000000002); +test(100, 99.99999999999999, 100.00000000000001); +test(100000, 99999.99999999999, 100000.00000000001); +test(10000000000, 9999999999.999998, 10000000000.000002); +test(1e+100, 9.999999999999998e+99, 1.0000000000000002e+100); +test(1e+223, 9.999999999999999e+222, 1.0000000000000002e+223); +test(1.7976931348623157e+308, 1.7976931348623155e+308, Infinity); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Math/fround.js b/js/src/tests/non262/Math/fround.js new file mode 100644 index 0000000000..353f798d5d --- /dev/null +++ b/js/src/tests/non262/Math/fround.js @@ -0,0 +1,81 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +// Some tests regarding conversion to Float32 +assertEq(Math.fround(), NaN); + +// Special values +assertEq(Math.fround(NaN), NaN); +assertEq(Math.fround(-Infinity), -Infinity); +assertEq(Math.fround(Infinity), Infinity); +assertEq(Math.fround(-0), -0); +assertEq(Math.fround(+0), +0); + +// Polyfill function for Float32 conversion +var toFloat32 = (function() { + var f32 = new Float32Array(1); + function f(x) { + f32[0] = x; + return f32[0]; + } + return f; +})(); + +// A test on a certain range of numbers, including big numbers, so that +// we get a loss in precision for some of them. +for (var i = 0; i < 64; ++i) { + var p = Math.pow(2, i) + 1; + assertEq(Math.fround(p), toFloat32(p)); + assertEq(Math.fround(-p), toFloat32(-p)); +} + +/******************************************** +/* Tests on maximal Float32 / Double values * +/*******************************************/ +function maxValue(exponentWidth, significandWidth) { + var n = 0; + var maxExp = Math.pow(2, exponentWidth - 1) - 1; + for (var i = significandWidth; i >= 0; i--) + n += Math.pow(2, maxExp - i); + return n; +} + +var DBL_MAX = maxValue(11, 52); +assertEq(DBL_MAX, Number.MAX_VALUE); // sanity check + +// Finite as a double, too big for a float +assertEq(Math.fround(DBL_MAX), Infinity); + +var FLT_MAX = maxValue(8, 23); +assertEq(Math.fround(FLT_MAX), FLT_MAX); +assertEq(Math.fround(FLT_MAX + Math.pow(2, Math.pow(2, 8 - 1) - 1 - 23 - 2)), FLT_MAX); // round-nearest rounds down to FLT_MAX +assertEq(Math.fround(FLT_MAX + Math.pow(2, Math.pow(2, 8 - 1) - 1 - 23 - 1)), Infinity); // no longer rounds down to FLT_MAX + +/********************************************************* +/******* Tests on denormalizations and roundings ********* +/********************************************************/ + +function minValue(exponentWidth, significandWidth) { + return Math.pow(2, -(Math.pow(2, exponentWidth - 1) - 2) - significandWidth); +} + +var DBL_MIN = Math.pow(2, -1074); +assertEq(DBL_MIN, Number.MIN_VALUE); // sanity check + +// Too small for a float +assertEq(Math.fround(DBL_MIN), 0); + +var FLT_MIN = minValue(8, 23); +assertEq(Math.fround(FLT_MIN), FLT_MIN); + +assertEq(Math.fround(FLT_MIN / 2), 0); // halfway, round-nearest rounds down to 0 (even) +assertEq(Math.fround(FLT_MIN / 2 + Math.pow(2, -202)), FLT_MIN); // first double > FLT_MIN / 2, rounds up to FLT_MIN + +assertEq(Math.fround(-FLT_MIN), -FLT_MIN); + +assertEq(Math.fround(-FLT_MIN / 2), -0); // halfway, round-nearest rounds up to -0 (even) +assertEq(Math.fround(-FLT_MIN / 2 - Math.pow(2, -202)), -FLT_MIN); // first double < -FLT_MIN / 2, rounds down to -FLT_MIN + +reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Math/log10-approx.js b/js/src/tests/non262/Math/log10-approx.js new file mode 100644 index 0000000000..0489448513 --- /dev/null +++ b/js/src/tests/non262/Math/log10-approx.js @@ -0,0 +1,9 @@ +assertNear(Math.log10(2), 0.3010299956639812); +assertNear(Math.log10(7), 0.8450980400142568); +assertNear(Math.log10(Math.E), Math.LOG10E); + +for (var i = -10; i < 10; i++) + assertNear(Math.log10(Math.pow(10, i)), i); + +reportCompare(0, 0, 'ok'); + diff --git a/js/src/tests/non262/Math/log10-exact.js b/js/src/tests/non262/Math/log10-exact.js new file mode 100644 index 0000000000..0c125306bf --- /dev/null +++ b/js/src/tests/non262/Math/log10-exact.js @@ -0,0 +1,30 @@ +// Properties of Math.log10 that are guaranteed by the spec. + +// If x is NaN, the result is NaN. +assertEq(Math.log10(NaN), NaN); + +// If x is less than 0, the result is NaN. +assertEq(Math.log10(-1e-10), NaN); +assertEq(Math.log10(-1e-5), NaN); +assertEq(Math.log10(-1e-1), NaN); +assertEq(Math.log10(-Number.MIN_VALUE), NaN); +assertEq(Math.log10(-Number.MAX_VALUE), NaN); +assertEq(Math.log10(-Infinity), NaN); + +for (var i = -1; i > -10; i--) + assertEq(Math.log10(i), NaN); + +// If x is +0, the result is −∞. +assertEq(Math.log10(+0), -Infinity); + +// If x is −0, the result is −∞. +assertEq(Math.log10(-0), -Infinity); + +// If x is 1, the result is +0. +assertEq(Math.log10(1), +0); + +// If x is +∞, the result is +∞. +assertEq(Math.log10(Infinity), Infinity); + + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Math/log1p-approx.js b/js/src/tests/non262/Math/log1p-approx.js new file mode 100644 index 0000000000..f1d120af68 --- /dev/null +++ b/js/src/tests/non262/Math/log1p-approx.js @@ -0,0 +1,20 @@ +assertNear(Math.log1p(1e-300), 1e-300); +assertNear(Math.log1p(1e-15), 9.999999999999995e-16); +assertNear(Math.log1p(1e-6), 9.999995000003334e-7); + +var log1p_data = [ + [ 1.875817529344e-70, 1.875817529344e-70 ], + [ 6.261923313140869e-30, 6.261923313140869e-30 ], + [ 7.09962844069878e-15, 7.099628440698755e-15 ], + [ 1.3671879628418538e-12, 1.3671879628409192e-12 ], + [ 2.114990849122478e-10, 2.1149908488988187e-10 ], + [ 1.6900931765206906e-8, 1.690093162238616e-8 ], + [ 0.0000709962844069878, 0.00007099376429006658 ], + [ 0.0016793412882520897, 0.00167793277137076 ], + [ 0.011404608812881634, 0.011340066517988035 ], +]; + +for (var [x, y] of log1p_data) + assertNear(Math.log1p(x), y); + +reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Math/log1p-exact.js b/js/src/tests/non262/Math/log1p-exact.js new file mode 100644 index 0000000000..bec11b6597 --- /dev/null +++ b/js/src/tests/non262/Math/log1p-exact.js @@ -0,0 +1,29 @@ +// Properties of Math.log1p that are guaranteed by the spec. + +// If x is NaN, the result is NaN. +assertEq(Math.log1p(NaN), NaN); + +// If x is less than -1, the result is NaN. +assertEq(Math.log1p(-1 - 1e-10), NaN); +assertEq(Math.log1p(-1 - 1e-5), NaN); +assertEq(Math.log1p(-1 - 1e-1), NaN); +assertEq(Math.log1p(-ONE_PLUS_EPSILON), NaN); + +for (var i = -2; i > -20; i--) + assertEq(Math.log1p(i), NaN); + +// If x is -1, the result is -∞. +assertEq(Math.log1p(-1), -Infinity); + +// If x is +0, the result is +0. +assertEq(Math.log1p(+0), +0); + +// If x is −0, the result is −0. +assertEq(Math.log1p(-0), -0); + +// If x is +∞, the result is +∞. +assertEq(Math.log1p(Infinity), Infinity); + + +reportCompare(0, 0, "ok"); + diff --git a/js/src/tests/non262/Math/log2-approx.js b/js/src/tests/non262/Math/log2-approx.js new file mode 100644 index 0000000000..954f4c1cf9 --- /dev/null +++ b/js/src/tests/non262/Math/log2-approx.js @@ -0,0 +1,8 @@ +for (var i = -1074; i < 1023; i++) + assertNear(Math.log2(Math.pow(2, i)), i); + +assertNear(Math.log2(5), 2.321928094887362); +assertNear(Math.log2(7), 2.807354922057604); +assertNear(Math.log2(Math.E), Math.LOG2E); + +reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Math/log2-exact.js b/js/src/tests/non262/Math/log2-exact.js new file mode 100644 index 0000000000..160034ddb8 --- /dev/null +++ b/js/src/tests/non262/Math/log2-exact.js @@ -0,0 +1,30 @@ +// Properties of Math.log2 that are guaranteed by the spec. + +// If x is NaN, the result is NaN. +assertEq(Math.log2(NaN), NaN); + +// If x is less than 0, the result is NaN. +assertEq(Math.log2(-1e-10), NaN); +assertEq(Math.log2(-1e-5), NaN); +assertEq(Math.log2(-1e-1), NaN); +assertEq(Math.log2(-Number.MIN_VALUE), NaN); +assertEq(Math.log2(-Number.MAX_VALUE), NaN); +assertEq(Math.log2(-Infinity), NaN); + +for (var i = -1; i > -10; i--) + assertEq(Math.log2(i), NaN); + +// If x is +0, the result is −∞. +assertEq(Math.log2(+0), -Infinity); + +// If x is −0, the result is −∞. +assertEq(Math.log2(-0), -Infinity); + +// If x is 1, the result is +0. +assertEq(Math.log2(1), +0); + +// If x is +∞, the result is +∞. +assertEq(Math.log2(Infinity), Infinity); + + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Math/pow-approx-pow10.js b/js/src/tests/non262/Math/pow-approx-pow10.js new file mode 100644 index 0000000000..c95eeab428 --- /dev/null +++ b/js/src/tests/non262/Math/pow-approx-pow10.js @@ -0,0 +1,51 @@ +if (typeof fdlibm === "undefined") { + var fdlibm = SpecialPowers.Cu.getJSTestingFunctions().fdlibm; +} + +const f64 = new Float64Array(1); +const ui64 = new BigUint64Array(f64.buffer); + +function toBits(n) { + f64[0] = n; + return ui64[0]; +} + +function errorInULP(actual, expected) { + // Handle NaN and +0/-0. + if (Object.is(actual, expected)) { + return 0; + } + + let x = toBits(actual); + let y = toBits(expected); + return x <= y ? Number(y - x) : Number(x - y); +} + +const maxExponent = Math.trunc(Math.log10(Number.MAX_VALUE)); +const minExponent = Math.trunc(Math.log10(Number.MIN_VALUE)); + +assertEq(Math.pow(10, maxExponent + 1), Infinity); +assertEq(Math.pow(10, minExponent - 1), 0); + +// Ensure the error is less than 2 ULP when compared to fdlibm. +for (let i = minExponent; i <= maxExponent; ++i) { + let actual = Math.pow(10, i); + let expected = fdlibm.pow(10, i); + let error = errorInULP(actual, expected); + + assertEq(error < 2, true, + `${10} ** ${i}: ${actual} (${toBits(actual).toString(16)}) != ${expected} (${toBits(expected).toString(16)})`); +} + +// Ensure the error is less than 2 ULP when compared to parsed string |1ep|. +for (let i = minExponent; i <= maxExponent; ++i) { + let actual = Math.pow(10, i); + let expected = Number("1e" + i); + let error = errorInULP(actual, expected); + + assertEq(error < 2, true, + `${10} ** ${i}: ${actual} (${toBits(actual).toString(16)}) != ${expected} (${toBits(expected).toString(16)})`); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Math/pow-approx.js b/js/src/tests/non262/Math/pow-approx.js new file mode 100644 index 0000000000..11d009158c --- /dev/null +++ b/js/src/tests/non262/Math/pow-approx.js @@ -0,0 +1,568 @@ +if (typeof fdlibm === "undefined") { + var fdlibm = SpecialPowers.Cu.getJSTestingFunctions().fdlibm; +} + +if (typeof getBuildConfiguration === "undefined") { + var getBuildConfiguration = SpecialPowers.Cu.getJSTestingFunctions().getBuildConfiguration; +} + +const f64 = new Float64Array(1); +const ui64 = new BigUint64Array(f64.buffer); + +function toBits(n) { + f64[0] = n; + return ui64[0]; +} + +function errorInULP(actual, expected) { + // Handle NaN and +0/-0. + if (Object.is(actual, expected)) { + return 0; + } + + let x = toBits(actual); + let y = toBits(expected); + return x <= y ? Number(y - x) : Number(x - y); +} + +// Test methodology: +// +// Generate test cases for inputs where the original js::powi implementation +// returns a different result than std::pow. If such inputs where found, compare +// them against fdlibm::pow to find inputs where the error is larger than 1 ULP. +// +// Compile with: +// -std=c++17 -O3 -msse -msse2 -mfpmath=sse -fno-math-errno -fno-exceptions -fno-rtti -march=native +// +// static bool test(double x, int32_t y) { +// if (std::isnan(x)) { +// return true; +// } +// +// double t = js::powi(x, y); +// double u = std::pow(x, static_cast(y)); +// if (t == u) { +// return true; +// } +// +// uint64_t a; +// std::memcpy(&a, &t, sizeof(double)); +// +// uint64_t b; +// std::memcpy(&b, &u, sizeof(double)); +// +// double v = fdlibm::pow(x, y); +// +// uint64_t c; +// std::memcpy(&c, &v, sizeof(double)); +// +// double w = musl::pow(x, y); +// +// uint64_t d; +// std::memcpy(&d, &w, sizeof(double)); +// +// // Expect at most 1 ULP difference between std::pow and fdlibm::pow. +// if ((b < c && c - b > 1) || (b > c && b - c > 1)) { +// printf("!!! [fdlibm] %.53f ** %d: 0x%" PRIx64 " != 0x%" PRIx64 "\n", x, y, b, c); +// exit(1); +// } +// +// // Expect at most 1 ULP difference between std::pow and musl::pow. +// if ((b < d && d - b > 1) || (b > d && b - d > 1)) { +// printf("!!! [musl] %.53f ** %d: 0x%" PRIx64 " != 0x%" PRIx64 "\n", x, y, b, d); +// exit(1); +// } +// +// // Accept 1 ULP difference between js::powi and fdlibm::pow. +// if ((a <= c && c - a <= 1) || (a >= c && a - c <= 1)) { +// return true; +// } +// +// // Output if a larger error was found. +// printf("%.53f ** %d: 0x%" PRIx64 " != 0x%" PRIx64 " (0x%" PRIx64 ") (0x%" PRIx64 ")\n", x, y, a, b, c, d); +// return false; +// } +// +// int main() { +// // Use mt19937 for reproducible results. +// std::mt19937_64 gen64; +// std::mt19937 gen32; +// +// for (uint64_t i = 0; i < 100'000'000'000; ++i) { +// uint64_t x = gen64(); +// int32_t y = gen32(); +// +// double f; +// std::memcpy(&f, &x, sizeof(double)); +// +// test(f, y); +// } +// } + +// Raw output: +// +// 0.99998738156596089776684266325901262462139129638671875 ** 38583256: 0x140854811fb319e7 != 0x140854811fe4d778 (0x140854811fe4d778) (0x140854811fe4d778) +// -0.99843469603485224261874009243911132216453552246093750 ** 326215: 0x91dad4716de6fc4b != 0x91dad4716de5e587 (0x91dad4716de5e588) (0x91dad4716de5e587) +// 0.00003722856305626354357250426541092735988058848306537 ** -33: 0x5e47357c3582e49e != 0x5e47357c3582e4a3 (0x5e47357c3582e4a3) (0x5e47357c3582e4a3) +// -0.99996909838479330900895547529216855764389038085937500 ** 17078527: 0x9058409e5ea3b80a != 0x9058409e5eb11ef4 (0x9058409e5eb11ef4) (0x9058409e5eb11ef4) +// 0.99992690642006631929206150743993930518627166748046875 ** -6725291: 0x6c42a167a8b7c0b2 != 0x6c42a167a8b81d0e (0x6c42a167a8b81d0e) (0x6c42a167a8b81d0e) +// -0.99879181217764612110698863034485839307308197021484375 ** 485128: 0xb0d9c6f2f710d24 != 0xb0d9c6f2f71708d (0xb0d9c6f2f71708d) (0xb0d9c6f2f71708d) +// -1.00560838484317760510577954846667125821113586425781250 ** 92252: 0x6e744b727536056b != 0x6e744b72753599a4 (0x6e744b72753599a4) (0x6e744b72753599a4) +// 0.99999532655875444930870798998512327671051025390625000 ** 93511912: 0x1886c29a53ed9332 != 0x1886c29a53cba724 (0x1886c29a53cba724) (0x1886c29a53cba724) +// -0.99989751779212987514711130643263459205627441406250000 ** -2864087: 0xda664b586d48712f != 0xda664b586d437e8c (0xda664b586d437e8c) (0xda664b586d437e8c) +// -239.35307289280868303649185691028833389282226562500000000 ** -90: 0x137a8b43006c4438 != 0x137a8b43006c443e (0x137a8b43006c443e) (0x137a8b43006c443e) +// 0.96128212369452570307259975379565730690956115722656250 ** -9670: 0x625d7eb275191f6f != 0x625d7eb2751920bf (0x625d7eb2751920c0) (0x625d7eb2751920bf) +// 0.99996078564218904283222855156054720282554626464843750 ** 10583765: 0x1a829de67930f619 != 0x1a829de67951cc2d (0x1a829de67951cc2d) (0x1a829de67951cc2d) +// -953.14032530394126752071315422654151916503906250000000000 ** 22: 0x4d8a6d863703112c != 0x4d8a6d863703112e (0x4d8a6d863703112e) (0x4d8a6d863703112e) +// 0.99857985216514444370972114484175108373165130615234375 ** 335918: 0x14e345eb84f09d46 != 0x14e345eb84f036f4 (0x14e345eb84f036f4) (0x14e345eb84f036f4) +// -1.20521595553711002857255607523256912827491760253906250 ** -2760: 0x117b0064dd165101 != 0x117b0064dd16511a (0x117b0064dd16511a) (0x117b0064dd16511a) +// -1.19074911947068473594413262617308646440505981445312500 ** 3884: 0x7d132c80ed6973f6 != 0x7d132c80ed697072 (0x7d132c80ed697072) (0x7d132c80ed697072) +// -0.99999908129426284819629699995857663452625274658203125 ** -172780371: 0xce400f20e4a13b1a != 0xce400f20e3e56454 (0xce400f20e3e56454) (0xce400f20e3e56454) +// -0.00000000000000000000000000007930552628950037082519209 ** 8: 0x1142888ad3062fc1 != 0x1142888ad3062fbe (0x1142888ad3062fbe) (0x1142888ad3062fbe) +// -0.99998583604065760521706351937609724700450897216796875 ** -5861784: 0x476b83d92617a928 != 0x476b83d9261b0d4e (0x476b83d9261b0d4e) (0x476b83d9261b0d4e) +// 0.99989915564587761309667257592082023620605468750000000 ** 5468367: 0xe34d25f36eef64b != 0xe34d25f36f555ca (0xe34d25f36f555ca) (0xe34d25f36f555ca) +// 0.99977805581863743444870351595454849302768707275390625 ** -130493: 0x428ba17ba9286df6 != 0x428ba17ba9282f94 (0x428ba17ba9282f94) (0x428ba17ba9282f94) +// 29.19821057723854806909002945758402347564697265625000000 ** -20: 0x39d8ffec76e30251 != 0x39d8ffec76e3024a (0x39d8ffec76e3024a) (0x39d8ffec76e3024a) +// 0.99985373283040668290766461723251268267631530761718750 ** 2345687: 0x20ff8c2fd8e5b4e0 != 0x20ff8c2fd8e00564 (0x20ff8c2fd8e00564) (0x20ff8c2fd8e00564) +// -0.88383265987178571965188211834174580872058868408203125 ** -841: 0xc94c6878de27b17c != 0xc94c6878de27b20d (0xc94c6878de27b20d) (0xc94c6878de27b20d) +// 0.99999589815682188298495702838408760726451873779296875 ** 72449292: 0x25233af2e809c6a6 != 0x25233af2e87ddc61 (0x25233af2e87ddc61) (0x25233af2e87ddc61) +// 345736476.13618659973144531250000000000000000000000000000000000 ** -16: 0x2391db755176ac1b != 0x2391db755176ac19 (0x2391db755176ac19) (0x2391db755176ac19) +// -0.99999307321818442506611290809814818203449249267578125 ** -55045397: 0xe250f3d69f25ec86 != 0xe250f3d69f03e875 (0xe250f3d69f03e875) (0xe250f3d69f03e875) +// 1419676.56599932140670716762542724609375000000000000000000000 ** 25: 0x5fde72aa74287c2d != 0x5fde72aa74287c30 (0x5fde72aa74287c30) (0x5fde72aa74287c30) +// 0.95797249286536323431562323094112798571586608886718750 ** -11483: 0x6c63b79e88c07b6f != 0x6c63b79e88c07a3f (0x6c63b79e88c07a3f) (0x6c63b79e88c07a3f) +// 0.99998135132609855535434917328529991209506988525390625 ** 5682278: 0x3661650feb28b969 != 0x3661650feb22b7ed (0x3661650feb22b7ed) (0x3661650feb22b7ed) +// -1.02020595459010832151136582979233935475349426269531250 ** -1668: 0x3ced0e90ddfec9a3 != 0x3ced0e90ddfecabc (0x3ced0e90ddfecabc) (0x3ced0e90ddfecabc) +// 0.97281701550260646360612781791132874786853790283203125 ** 13717: 0x1dd88a88f24fc0d5 != 0x1dd88a88f24fb801 (0x1dd88a88f24fb801) (0x1dd88a88f24fb801) +// -0.88724290003841266294415390802896581590175628662109375 ** -3437: 0xe502ab8ea591420d != 0xe502ab8ea5914139 (0xe502ab8ea5914139) (0xe502ab8ea5914139) +// -0.99998630320599690701754980182158760726451873779296875 ** -11251995: 0xcdd44ff462cfbf32 != 0xcdd44ff462dbdcb2 (0xcdd44ff462dbdcb2) (0xcdd44ff462dbdcb2) +// -0.99995743703658013235013868325040675699710845947265625 ** 13995099: 0x8a38604324e009d5 != 0x8a38604324c2ec7d (0x8a38604324c2ec7d) (0x8a38604324c2ec7d) +// 0.99991090354494038816568490801728330552577972412109375 ** 7116340: 0x6c2ca56237c8161 != 0x6c2ca562366c00b (0x6c2ca562366c00b) (0x6c2ca562366c00b) +// 0.00000022955540324908999561342678487341206761129797087 ** 27: 0x1ab703277bbb112d != 0x1ab703277bbb1131 (0x1ab703277bbb1130) (0x1ab703277bbb1131) +// -1.00000041289256280663266807096078991889953613281250000 ** -365287834: 0x3255339a24caec8a != 0x3255339a26f00dc8 (0x3255339a26f00dc8) (0x3255339a26f00dc8) +// -1.38949508997780957209045027411775663495063781738281250 ** 1996: 0x7b22ad71344bbd0b != 0x7b22ad71344bbddf (0x7b22ad71344bbddf) (0x7b22ad71344bbddf) +// 0.99999867528282249118376512342365458607673645019531250 ** 164253172: 0x2c50f93fbc72a2b4 != 0x2c50f93fbb2d2fd4 (0x2c50f93fbb2d2fd4) (0x2c50f93fbb2d2fd4) +// 1.00356688770562074708436739456374198198318481445312500 ** -141698: 0x12717fb35c5fd169 != 0x12717fb35c5ff8c8 (0x12717fb35c5ff8c8) (0x12717fb35c5ff8c8) +// 368710687472107.18750000000000000000000000000000000000000000000000000 ** -20: 0x37282f0ae9be13c != 0x37282f0ae9be138 (0x37282f0ae9be138) (0x37282f0ae9be138) +// 0.99246668780181890312519499275367707014083862304687500 ** -44617: 0x5e5ad2c000333e50 != 0x5e5ad2c0003351f5 (0x5e5ad2c0003351f5) (0x5e5ad2c0003351f5) +// 1.13820783188362395499382273555966094136238098144531250 ** 1411: 0x506701df16f3a891 != 0x506701df16f3a70d (0x506701df16f3a70d) (0x506701df16f3a70d) +// -0.99671841783028414241130121808964759111404418945312500 ** 97041: 0xa32c44e6e77f8d3b != 0xa32c44e6e77f6a7a (0xa32c44e6e77f6a7a) (0xa32c44e6e77f6a7a) +// -0.57021831816264889614132016504299826920032501220703125 ** -802: 0x688ef2cc36fa60b3 != 0x688ef2cc36fa6064 (0x688ef2cc36fa6064) (0x688ef2cc36fa6064) +// -0.97423450510790443601649712945800274610519409179687500 ** 23570: 0x874c760d601ec94 != 0x874c760d601e66f (0x874c760d601e66f) (0x874c760d601e66f) +// -0.98067196425761504752216524138930253684520721435546875 ** -19882: 0x62ec606ceb9af0ae != 0x62ec606ceb9ae89c (0x62ec606ceb9ae89c) (0x62ec606ceb9ae89c) +// 0.99683039770073134100414335989626124501228332519531250 ** -29823: 0x487816b919332b03 != 0x487816b919333fe4 (0x487816b919333fe4) (0x487816b919333fe4) +// 0.99882797644578258378089685720624402165412902832031250 ** -540990: 0x792372efd5ca5ad2 != 0x792372efd5c92857 (0x792372efd5c92857) (0x792372efd5c92857) + +const testCases = [ + [0.99998738156596089776684266325901262462139129638671875 , 38583256], + [-0.99843469603485224261874009243911132216453552246093750 , 326215], + [0.00003722856305626354357250426541092735988058848306537 , -33], + [-0.99996909838479330900895547529216855764389038085937500 , 17078527], + [0.99992690642006631929206150743993930518627166748046875 , -6725291], + [-0.99879181217764612110698863034485839307308197021484375 , 485128], + [-1.00560838484317760510577954846667125821113586425781250 , 92252], + [0.99999532655875444930870798998512327671051025390625000 , 93511912], + [-0.99989751779212987514711130643263459205627441406250000 , -2864087], + [-239.35307289280868303649185691028833389282226562500000000 , -90], + [0.96128212369452570307259975379565730690956115722656250 , -9670], + [0.99996078564218904283222855156054720282554626464843750 , 10583765], + [-953.14032530394126752071315422654151916503906250000000000 , 22], + [0.99857985216514444370972114484175108373165130615234375 , 335918], + [-1.20521595553711002857255607523256912827491760253906250 , -2760], + [-1.19074911947068473594413262617308646440505981445312500 , 3884], + [-0.99999908129426284819629699995857663452625274658203125 , -172780371], + [-0.00000000000000000000000000007930552628950037082519209 , 8], + [-0.99998583604065760521706351937609724700450897216796875 , -5861784], + [0.99989915564587761309667257592082023620605468750000000 , 5468367], + [0.99977805581863743444870351595454849302768707275390625 , -130493], + [29.19821057723854806909002945758402347564697265625000000 , -20], + [0.99985373283040668290766461723251268267631530761718750 , 2345687], + [-0.88383265987178571965188211834174580872058868408203125 , -841], + [0.99999589815682188298495702838408760726451873779296875 , 72449292], + [345736476.13618659973144531250000000000000000000000000000000000 , -16], + [-0.99999307321818442506611290809814818203449249267578125 , -55045397], + [1419676.56599932140670716762542724609375000000000000000000000 , 25], + [0.95797249286536323431562323094112798571586608886718750 , -11483], + [0.99998135132609855535434917328529991209506988525390625 , 5682278], + [-1.02020595459010832151136582979233935475349426269531250 , -1668], + [0.97281701550260646360612781791132874786853790283203125 , 13717], + [-0.88724290003841266294415390802896581590175628662109375 , -3437], + [-0.99998630320599690701754980182158760726451873779296875 , -11251995], + [-0.99995743703658013235013868325040675699710845947265625 , 13995099], + [0.99991090354494038816568490801728330552577972412109375 , 7116340], + [0.00000022955540324908999561342678487341206761129797087 , 27], + [-1.00000041289256280663266807096078991889953613281250000 , -365287834], + [-1.38949508997780957209045027411775663495063781738281250 , 1996], + [0.99999867528282249118376512342365458607673645019531250 , 164253172], + [1.00356688770562074708436739456374198198318481445312500 , -141698], + [368710687472107.18750000000000000000000000000000000000000000000000000 , -20], + [0.99246668780181890312519499275367707014083862304687500 , -44617], + [1.13820783188362395499382273555966094136238098144531250 , 1411], + [-0.99671841783028414241130121808964759111404418945312500 , 97041], + [-0.57021831816264889614132016504299826920032501220703125 , -802], + [-0.97423450510790443601649712945800274610519409179687500 , 23570], + [-0.98067196425761504752216524138930253684520721435546875 , -19882], + [0.99683039770073134100414335989626124501228332519531250 , -29823], + [0.99882797644578258378089685720624402165412902832031250 , -540990], +]; + +// Test program modified to avoid bases with |abs(x) < 1| and large exponents. +// +// ```cpp +// // Skip over likely denormals. +// if (-1 < f && f < 0) { +// f -= 1; +// } else if (0 < f && f < 1) { +// f += 1; +// } +// +// // Keep the power small. +// y &= 63; +// ``` +// +// 7.86990183266223297664510027971118688583374023437500000 ** 54: 0x49fa67548289784a != 0x49fa675482897851 (0x49fa675482897850) (0x49fa675482897851) +// -1.00000018751738117828153917798772454261779785156250000 ** 25: 0xbff00004ea6921f6 != 0xbff00004ea6921fc (0xbff00004ea6921fc) (0xbff00004ea6921fc) +// 1.19908234423429393977755808009533211588859558105468750 ** 58: 0x40e246fe7b30c6ec != 0x40e246fe7b30c6e6 (0x40e246fe7b30c6e6) (0x40e246fe7b30c6e6) +// 1.00000649317438283780745678086532279849052429199218750 ** 42: 0x3ff0011dffabb95c != 0x3ff0011dffabb950 (0x3ff0011dffabb950) (0x3ff0011dffabb950) +// 863370098.16819441318511962890625000000000000000000000000000000 ** 27: 0x7206b860614eb6df != 0x7206b860614eb6d9 (0x7206b860614eb6d9) (0x7206b860614eb6d9) +// -1.00011928123711690830077714053913950920104980468750000 ** 57: 0xbff01bf129d0ffab != 0xbff01bf129d0ffbf (0xbff01bf129d0ffbf) (0xbff01bf129d0ffbf) +// -1.14006037237328494704513559554470703005790710449218750 ** 30: 0x404983fd4d57c4aa != 0x404983fd4d57c4a0 (0x404983fd4d57c4a0) (0x404983fd4d57c4a0) +// -447.11057737163486081044538877904415130615234375000000000 ** 8: 0x4455a4e4be220fce != 0x4455a4e4be220fd0 (0x4455a4e4be220fd0) (0x4455a4e4be220fd0) +// -1.03656507831253685836259137431625276803970336914062500 ** 20: 0x4000681e0886d6db != 0x4000681e0886d6d9 (0x4000681e0886d6d9) (0x4000681e0886d6d9) +// -1.00000465330344945336094042431795969605445861816406250 ** 41: 0xbff000c81257efc1 != 0xbff000c81257efc6 (0xbff000c81257efc6) (0xbff000c81257efc6) +// -1.00002726631492944164847358479164540767669677734375000 ** 14: 0x3ff00190579a2f93 != 0x3ff00190579a2f90 (0x3ff00190579a2f90) (0x3ff00190579a2f90) +// 2512068.57641875604167580604553222656250000000000000000000000 ** 26: 0x627b50512391a46e != 0x627b50512391a46c (0x627b50512391a46c) (0x627b50512391a46c) +// 3309586784.85019683837890625000000000000000000000000000000000000 ** 30: 0x7b3a5b69a3a40717 != 0x7b3a5b69a3a40719 (0x7b3a5b69a3a40719) (0x7b3a5b69a3a40719) +// 1.40742719307547781149025922786677256226539611816406250 ** 19: 0x4084a6ad66b5f1ce != 0x4084a6ad66b5f1d1 (0x4084a6ad66b5f1d0) (0x4084a6ad66b5f1d1) +// 1.00035740860596344958821646287105977535247802734375000 ** 36: 0x3ff0350873b3189e != 0x3ff0350873b318a0 (0x3ff0350873b318a0) (0x3ff0350873b318a0) +testCases.push( + [7.86990183266223297664510027971118688583374023437500000 , 54], + [-1.00000018751738117828153917798772454261779785156250000 , 25], + [1.19908234423429393977755808009533211588859558105468750 , 58], + [1.00000649317438283780745678086532279849052429199218750 , 42], + [863370098.16819441318511962890625000000000000000000000000000000 , 27], + [-1.00011928123711690830077714053913950920104980468750000 , 57], + [-1.14006037237328494704513559554470703005790710449218750 , 30], + [-447.11057737163486081044538877904415130615234375000000000 , 8], + [-1.03656507831253685836259137431625276803970336914062500 , 20], + [-1.00000465330344945336094042431795969605445861816406250 , 41], + [-1.00002726631492944164847358479164540767669677734375000 , 14], + [2512068.57641875604167580604553222656250000000000000000000000 , 26], + [3309586784.85019683837890625000000000000000000000000000000000000 , 30], + [1.40742719307547781149025922786677256226539611816406250 , 19], + [1.00035740860596344958821646287105977535247802734375000 , 36], +); + +// Test program modified to only use small integer bases (< 20) and positive exponents. +// +// ```cpp +// f = static_cast(x); +// f = std::fmod(f, 20); +// y &= 63; +// ``` +// +// 13.00000000000000000000000000000000000000000000000000000 ** 31: 0x471a3d23b248d522 != 0x471a3d23b248d520 (0x471a3d23b248d520) (0x471a3d23b248d520) +// 13.00000000000000000000000000000000000000000000000000000 ** 41: 0x496a51a4d0054bb2 != 0x496a51a4d0054bb1 (0x496a51a4d0054bb0) (0x496a51a4d0054bb1) +// 13.00000000000000000000000000000000000000000000000000000 ** 51: 0x4bba6635f3af40fa != 0x4bba6635f3af40f8 (0x4bba6635f3af40f8) (0x4bba6635f3af40f8) +// 13.00000000000000000000000000000000000000000000000000000 ** 58: 0x4d58af19e7576d60 != 0x4d58af19e7576d5e (0x4d58af19e7576d5e) (0x4d58af19e7576d5e) +// 13.00000000000000000000000000000000000000000000000000000 ** 63: 0x4e817b180a97c789 != 0x4e817b180a97c787 (0x4e817b180a97c787) (0x4e817b180a97c787) +// 11.00000000000000000000000000000000000000000000000000000 ** 63: 0x4d8ec9288a0088ce != 0x4d8ec9288a0088d0 (0x4d8ec9288a0088d0) (0x4d8ec9288a0088d0) +// 13.00000000000000000000000000000000000000000000000000000 ** 47: 0x4ace49afd4c20163 != 0x4ace49afd4c20161 (0x4ace49afd4c20161) (0x4ace49afd4c20161) +// 13.00000000000000000000000000000000000000000000000000000 ** 41: 0x496a51a4d0054bb2 != 0x496a51a4d0054bb1 (0x496a51a4d0054bb0) (0x496a51a4d0054bb1) +// 13.00000000000000000000000000000000000000000000000000000 ** 63: 0x4e817b180a97c789 != 0x4e817b180a97c787 (0x4e817b180a97c787) (0x4e817b180a97c787) +// 13.00000000000000000000000000000000000000000000000000000 ** 31: 0x471a3d23b248d522 != 0x471a3d23b248d520 (0x471a3d23b248d520) (0x471a3d23b248d520) +// 13.00000000000000000000000000000000000000000000000000000 ** 49: 0x4b43fea5137412eb != 0x4b43fea5137412e9 (0x4b43fea5137412e9) (0x4b43fea5137412e9) +// 13.00000000000000000000000000000000000000000000000000000 ** 58: 0x4d58af19e7576d60 != 0x4d58af19e7576d5e (0x4d58af19e7576d5e) (0x4d58af19e7576d5e) +// 13.00000000000000000000000000000000000000000000000000000 ** 31: 0x471a3d23b248d522 != 0x471a3d23b248d520 (0x471a3d23b248d520) (0x471a3d23b248d520) +// 11.00000000000000000000000000000000000000000000000000000 ** 63: 0x4d8ec9288a0088ce != 0x4d8ec9288a0088d0 (0x4d8ec9288a0088d0) (0x4d8ec9288a0088d0) +// 13.00000000000000000000000000000000000000000000000000000 ** 31: 0x471a3d23b248d522 != 0x471a3d23b248d520 (0x471a3d23b248d520) (0x471a3d23b248d520) +testCases.push( + [13.00000000000000000000000000000000000000000000000000000 , 31], + [13.00000000000000000000000000000000000000000000000000000 , 41], + [13.00000000000000000000000000000000000000000000000000000 , 51], + [13.00000000000000000000000000000000000000000000000000000 , 58], + [13.00000000000000000000000000000000000000000000000000000 , 63], + [11.00000000000000000000000000000000000000000000000000000 , 63], + [13.00000000000000000000000000000000000000000000000000000 , 47], + [13.00000000000000000000000000000000000000000000000000000 , 41], + [13.00000000000000000000000000000000000000000000000000000 , 63], + [13.00000000000000000000000000000000000000000000000000000 , 31], + [13.00000000000000000000000000000000000000000000000000000 , 49], + [13.00000000000000000000000000000000000000000000000000000 , 58], + [13.00000000000000000000000000000000000000000000000000000 , 31], + [11.00000000000000000000000000000000000000000000000000000 , 63], + [13.00000000000000000000000000000000000000000000000000000 , 31], +); + +// Test program modified to only use small integer bases (< 20) and negative exponents. +// +// ```cpp +// f = static_cast(x); +// f = std::fmod(f, 20); +// y &= 63; +// y = -y; +// ``` +// +// 14.00000000000000000000000000000000000000000000000000000 ** -57: 0x325f938745f05e58 != 0x325f938745f05e5a (0x325f938745f05e5a) (0x325f938745f05e5a) +// 11.00000000000000000000000000000000000000000000000000000 ** -53: 0x34791bddc7b3025a != 0x34791bddc7b30259 (0x34791bddc7b30258) (0x34791bddc7b30259) +// 7.00000000000000000000000000000000000000000000000000000 ** -57: 0x35ef938745f05e58 != 0x35ef938745f05e5a (0x35ef938745f05e5a) (0x35ef938745f05e5a) +// 15.00000000000000000000000000000000000000000000000000000 ** -50: 0x33b933babb6d9cd8 != 0x33b933babb6d9cda (0x33b933babb6d9cda) (0x33b933babb6d9cda) +// 14.00000000000000000000000000000000000000000000000000000 ** -57: 0x325f938745f05e58 != 0x325f938745f05e5a (0x325f938745f05e5a) (0x325f938745f05e5a) +// 13.00000000000000000000000000000000000000000000000000000 ** -33: 0x384d8ee9f0edfd7c != 0x384d8ee9f0edfd7d (0x384d8ee9f0edfd7e) (0x384d8ee9f0edfd7d) +// 19.00000000000000000000000000000000000000000000000000000 ** -53: 0x31dd0994e8aaf4e0 != 0x31dd0994e8aaf4e1 (0x31dd0994e8aaf4e2) (0x31dd0994e8aaf4e1) +// 15.00000000000000000000000000000000000000000000000000000 ** -50: 0x33b933babb6d9cd8 != 0x33b933babb6d9cda (0x33b933babb6d9cda) (0x33b933babb6d9cda) +// 14.00000000000000000000000000000000000000000000000000000 ** -57: 0x325f938745f05e58 != 0x325f938745f05e5a (0x325f938745f05e5a) (0x325f938745f05e5a) +// 13.00000000000000000000000000000000000000000000000000000 ** -63: 0x315d4a0a2c8d4bd8 != 0x315d4a0a2c8d4bdb (0x315d4a0a2c8d4bdb) (0x315d4a0a2c8d4bdb) +// 11.00000000000000000000000000000000000000000000000000000 ** -53: 0x34791bddc7b3025a != 0x34791bddc7b30259 (0x34791bddc7b30258) (0x34791bddc7b30259) +// 15.00000000000000000000000000000000000000000000000000000 ** -50: 0x33b933babb6d9cd8 != 0x33b933babb6d9cda (0x33b933babb6d9cda) (0x33b933babb6d9cda) +// 13.00000000000000000000000000000000000000000000000000000 ** -53: 0x33ad60ed868e2926 != 0x33ad60ed868e2928 (0x33ad60ed868e2928) (0x33ad60ed868e2928) +// 19.00000000000000000000000000000000000000000000000000000 ** -53: 0x31dd0994e8aaf4e0 != 0x31dd0994e8aaf4e1 (0x31dd0994e8aaf4e2) (0x31dd0994e8aaf4e1) +// 13.00000000000000000000000000000000000000000000000000000 ** -33: 0x384d8ee9f0edfd7c != 0x384d8ee9f0edfd7d (0x384d8ee9f0edfd7e) (0x384d8ee9f0edfd7d) +testCases.push( + [14.00000000000000000000000000000000000000000000000000000 , -57], + [11.00000000000000000000000000000000000000000000000000000 , -53], + [7.00000000000000000000000000000000000000000000000000000 , -57], + [15.00000000000000000000000000000000000000000000000000000 , -50], + [14.00000000000000000000000000000000000000000000000000000 , -57], + [13.00000000000000000000000000000000000000000000000000000 , -33], + [19.00000000000000000000000000000000000000000000000000000 , -53], + [15.00000000000000000000000000000000000000000000000000000 , -50], + [14.00000000000000000000000000000000000000000000000000000 , -57], + [13.00000000000000000000000000000000000000000000000000000 , -63], + [11.00000000000000000000000000000000000000000000000000000 , -53], + [15.00000000000000000000000000000000000000000000000000000 , -50], + [13.00000000000000000000000000000000000000000000000000000 , -53], + [19.00000000000000000000000000000000000000000000000000000 , -53], + [13.00000000000000000000000000000000000000000000000000000 , -33], +); + +// std::pow is less precise on Windows. +const maxError = getBuildConfiguration("windows") ? 3 : 1; + +// Ensure the error is less-or-equal to |maxError| ULP when compared to fdlibm. +for (let [x, y] of testCases) { + let actual = Math.pow(x, y); + let expected = fdlibm.pow(x, y); + let error = errorInULP(actual, expected); + + assertEq(error <= maxError, true, + `${x} ** ${y}: ${actual} (${toBits(actual).toString(16)}) != ${expected} (${toBits(expected).toString(16)})`); +} + +// Test program modified to use 4 as the exponent: +// +// ```cpp +// y = 4; +// ``` +// +// -0.00000000000000000000000000000749666789562697097993956 ** 4: 0x27bfdbe3cf0b7e1d != 0x27bfdbe3cf0b7e1b (0x27bfdbe3cf0b7e1b) (0x27bfdbe3cf0b7e1b) +// 0.00000000000000000000000000000000000000000000000000000 ** 4: 0xd3e1e77bd0d8f5d != 0xd3e1e77bd0d8f5f (0xd3e1e77bd0d8f5f) (0xd3e1e77bd0d8f5f) +// -0.00000000000000000000000000023705601542216470968966009 ** 4: 0x28fe60d2f5131d02 != 0x28fe60d2f5131d04 (0x28fe60d2f5131d04) (0x28fe60d2f5131d04) +// 0.00000000000000000000000000000000000000000000000000441 ** 4: 0x161dad0fa681c66c != 0x161dad0fa681c66b (0x161dad0fa681c66a) (0x161dad0fa681c66b) +// 0.00000000000000537255761599995092558925668894011631095 ** 4: 0x3414eb4baea214b6 != 0x3414eb4baea214b5 (0x3414eb4baea214b4) (0x3414eb4baea214b5) +// 0.01225688384384779339164595057809492573142051696777344 ** 4: 0x3e583bd550871dfc != 0x3e583bd550871dfd (0x3e583bd550871dfe) (0x3e583bd550871dfd) +// -0.00000000000000000000000000000000000000000000000000000 ** 4: 0xa59292360f6d326 != 0xa59292360f6d324 (0xa59292360f6d324) (0xa59292360f6d324) +// -0.00000000000000000000000000000000000000000000000000000 ** 4: 0x109fb7a8459811ec != 0x109fb7a8459811ed (0x109fb7a8459811ee) (0x109fb7a8459811ed) +// -120834175976112453093144522854609799898808186321228136949237230085114691584.00000000000000000000000000000000000000000000000000000 ** 4: 0x7d74dcc37a2d7dc2 != 0x7d74dcc37a2d7dc3 (0x7d74dcc37a2d7dc4) (0x7d74dcc37a2d7dc3) +// -6676.83140968165753292851150035858154296875000000000000000 ** 4: 0x431c3e0ef48fe66a != 0x431c3e0ef48fe66c (0x431c3e0ef48fe66c) (0x431c3e0ef48fe66c) +// -0.00000000000000000000000000000000000000000000039753861 ** 4: 0x1a3a87f39f288766 != 0x1a3a87f39f288764 (0x1a3a87f39f288764) (0x1a3a87f39f288764) +// 129749516186492032220917661696.00000000000000000000000000000000000000000000000000000 ** 4: 0x581cc58a512bdd10 != 0x581cc58a512bdd12 (0x581cc58a512bdd12) (0x581cc58a512bdd12) +// -1888635225450734959219733085647207705818299180319259746124169216.00000000000000000000000000000000000000000000000000000 ** 4: 0x747bc423aba49de6 != 0x747bc423aba49de5 (0x747bc423aba49de4) (0x747bc423aba49de5) +// 7934926680560039158281691725824.00000000000000000000000000000000000000000000000000000 ** 4: 0x5997fceb5eed5c94 != 0x5997fceb5eed5c93 (0x5997fceb5eed5c92) (0x5997fceb5eed5c93) +// -0.00000000000000579868166379701264244398310517312073637 ** 4: 0x341c635a1a764ef2 != 0x341c635a1a764ef0 (0x341c635a1a764ef0) (0x341c635a1a764ef0) +// +// +// Test program modified to avoid bases with |abs(x) < 1| and large exponents. +// +// ```cpp +// // Skip over likely denormals. +// if (-1 < f && f < 0) { +// f -= 1; +// } else if (0 < f && f < 1) { +// f += 1; +// } +// +// f = std::fmod(f, 20); +// +// y = 4; +// ``` +// +// 4.73347349464893341064453125000000000000000000000000000 ** 4: 0x407f604c239c2323 != 0x407f604c239c2321 (0x407f604c239c2321) (0x407f604c239c2321) +// -12.35635152040049433708190917968750000000000000000000000 ** 4: 0x40d6c3c0652f0948 != 0x40d6c3c0652f0949 (0x40d6c3c0652f094a) (0x40d6c3c0652f0949) +// -1.50385549572482823954544528533006086945533752441406250 ** 4: 0x40147581145bc6e6 != 0x40147581145bc6e7 (0x40147581145bc6e8) (0x40147581145bc6e7) +// -8.93048901623114943504333496093750000000000000000000000 ** 4: 0x40b8d8a463c28bd6 != 0x40b8d8a463c28bd7 (0x40b8d8a463c28bd8) (0x40b8d8a463c28bd7) +// 19.02711385915608843788504600524902343750000000000000000 ** 4: 0x40ffffa7d5df2562 != 0x40ffffa7d5df2560 (0x40ffffa7d5df2560) (0x40ffffa7d5df2560) +// 17.83878016096969076897948980331420898437500000000000000 ** 4: 0x40f8b914a6acb498 != 0x40f8b914a6acb497 (0x40f8b914a6acb496) (0x40f8b914a6acb497) +// 12.90541613101959228515625000000000000000000000000000000 ** 4: 0x40db16b4c2dafa0a != 0x40db16b4c2dafa0c (0x40db16b4c2dafa0c) (0x40db16b4c2dafa0c) +// -18.34655402903445065021514892578125000000000000000000000 ** 4: 0x40fba90e5b7bbc6a != 0x40fba90e5b7bbc6b (0x40fba90e5b7bbc6c) (0x40fba90e5b7bbc6b) +// -13.28634420270100235939025878906250000000000000000000000 ** 4: 0x40de6e70b9ed821a != 0x40de6e70b9ed821c (0x40de6e70b9ed821c) (0x40de6e70b9ed821c) +// 18.52965961024165153503417968750000000000000000000000000 ** 4: 0x40fcc800b850b01a != 0x40fcc800b850b018 (0x40fcc800b850b018) (0x40fcc800b850b018) +// 13.32226210648514097556471824645996093750000000000000000 ** 4: 0x40dec3063a559350 != 0x40dec3063a55934e (0x40dec3063a55934e) (0x40dec3063a55934e) +// 1.09174693829848346027233674249146133661270141601562500 ** 4: 0x3ff6bafe5bbe7532 != 0x3ff6bafe5bbe7533 (0x3ff6bafe5bbe7534) (0x3ff6bafe5bbe7533) +// 9.35059530444141273619607090950012207031250000000000000 ** 4: 0x40bddca3dd9f5c8f != 0x40bddca3dd9f5c91 (0x40bddca3dd9f5c91) (0x40bddca3dd9f5c91) +// 17.59552449546754360198974609375000000000000000000000000 ** 4: 0x40f766db2706f434 != 0x40f766db2706f435 (0x40f766db2706f436) (0x40f766db2706f435) +// 17.94561576098203659057617187500000000000000000000000000 ** 4: 0x40f952110041965c != 0x40f952110041965a (0x40f952110041965a) (0x40f952110041965a) +const testCases4 = [ + [-0.00000000000000000000000000000749666789562697097993956 , 4], + [0.00000000000000000000000000000000000000000000000000000 , 4], + [-0.00000000000000000000000000023705601542216470968966009 , 4], + [0.00000000000000000000000000000000000000000000000000441 , 4], + [0.00000000000000537255761599995092558925668894011631095 , 4], + [0.01225688384384779339164595057809492573142051696777344 , 4], + [-0.00000000000000000000000000000000000000000000000000000 , 4], + [-0.00000000000000000000000000000000000000000000000000000 , 4], + [-120834175976112453093144522854609799898808186321228136949237230085114691584.00000000000000000000000000000000000000000000000000000 , 4], + [-6676.83140968165753292851150035858154296875000000000000000 , 4], + [-0.00000000000000000000000000000000000000000000039753861 , 4], + [129749516186492032220917661696.00000000000000000000000000000000000000000000000000000 , 4], + [-1888635225450734959219733085647207705818299180319259746124169216.00000000000000000000000000000000000000000000000000000 , 4], + [7934926680560039158281691725824.00000000000000000000000000000000000000000000000000000 , 4], + [-0.00000000000000579868166379701264244398310517312073637 , 4], + + [4.73347349464893341064453125000000000000000000000000000 , 4], + [-12.35635152040049433708190917968750000000000000000000000 , 4], + [-1.50385549572482823954544528533006086945533752441406250 , 4], + [-8.93048901623114943504333496093750000000000000000000000 , 4], + [19.02711385915608843788504600524902343750000000000000000 , 4], + [17.83878016096969076897948980331420898437500000000000000 , 4], + [12.90541613101959228515625000000000000000000000000000000 , 4], + [-18.34655402903445065021514892578125000000000000000000000 , 4], + [-13.28634420270100235939025878906250000000000000000000000 , 4], + [18.52965961024165153503417968750000000000000000000000000 , 4], + [13.32226210648514097556471824645996093750000000000000000 , 4], + [1.09174693829848346027233674249146133661270141601562500 , 4], + [9.35059530444141273619607090950012207031250000000000000 , 4], + [17.59552449546754360198974609375000000000000000000000000 , 4], + [17.94561576098203659057617187500000000000000000000000000 , 4], +]; + +// Ensure the error is less-or-equal to 2 ULP when compared to fdlibm. +// +// This can produce a larger error than std::pow, because we evaluate +// |x ** 4| as |(x * x) * (x * x)| to match Ion. +for (let [x, y] of testCases4) { + let actual = Math.pow(x, y); + let expected = fdlibm.pow(x, y); + let error = errorInULP(actual, expected); + assertEq(error <= 2, true, + `${x} ** ${y}: ${actual} (${toBits(actual).toString(16)}) != ${expected} (${toBits(expected).toString(16)})`); +} + +for (let [x, y] of testCases4) { + // Replace |y| with a constant to trigger Ion optimisations. + let actual = Math.pow(x, 4); + let expected = fdlibm.pow(x, y); + let error = errorInULP(actual, expected); + assertEq(error <= 2, true, + `${x} ** ${y}: ${actual} (${toBits(actual).toString(16)}) != ${expected} (${toBits(expected).toString(16)})`); +} + +// Test program modified to use 3 as the exponent: +// +// ```cpp +// y = 3; +// ``` +// +// 196194373276.42089843750000000000000000000000000000000000000000000 ** 3: 0x46f745720bc58e22 != 0x46f745720bc58e23 (0x46f745720bc58e24) (0x46f745720bc58e23) +// 17260025115986696435331651385474892363490876322742272.00000000000000000000000000000000000000000000000000000 ** 3: 0x6077f8040eb542fc != 0x6077f8040eb542fb (0x6077f8040eb542fa) (0x6077f8040eb542fb) +// -0.00000000000000000000000000000000000000000000000000000 ** 3: 0x9307c17ddf2c4af6 != 0x9307c17ddf2c4af7 (0x9307c17ddf2c4af8) (0x9307c17ddf2c4af7) +// 2359506498398344427475761591701240715936602989985583832867274752.00000000000000000000000000000000000000000000000000000 ** 3: 0x6767960b1076dc24 != 0x6767960b1076dc25 (0x6767960b1076dc26) (0x6767960b1076dc25) +// 22724457948673043906745552566513068013978508710758109286797554897659283949989408425377792.00000000000000000000000000000000000000000000000000000 ** 3: 0x76f74ab82115b372 != 0x76f74ab82115b373 (0x76f74ab82115b374) (0x76f74ab82115b373) +// -1024872849611580448634200763411882795753013248.00000000000000000000000000000000000000000000000000000 ** 3: 0xdbf7b2694dce1d6c != 0xdbf7b2694dce1d6b (0xdbf7b2694dce1d6a) (0xdbf7b2694dce1d6b) +// -918435268181356203923125447950336.00000000000000000000000000000000000000000000000000000 ** 3: 0xd476ab3173dbfcc0 != 0xd476ab3173dbfcbf (0xd476ab3173dbfcbe) (0xd476ab3173dbfcbf) +// 558545783776545344834655968246618719333738303286453207040.00000000000000000000000000000000000000000000000000000 ** 3: 0x634716045b3ee61c != 0x634716045b3ee61b (0x634716045b3ee61a) (0x634716045b3ee61b) +// 0.00000000000000000000000000000000000000000000000000000 ** 3: 0x1c6f3bddc90315c != 0x1c6f3bddc90315b (0x1c6f3bddc90315a) (0x1c6f3bddc90315b) +// -0.00000000000261062225071774409619236799548496917242058 ** 3: 0xb8b7a667f8b6344e != 0xb8b7a667f8b6344f (0xb8b7a667f8b63450) (0xb8b7a667f8b6344f) +// 0.00000000000000000000000000000000000000000000012475377 ** 3: 0x23571f25316bb01e != 0x23571f25316bb01f (0x23571f25316bb020) (0x23571f25316bb01f) +// -0.00000000000000000000000000000000000000000000000000000 ** 3: 0x93f6c04c12acc76c != 0x93f6c04c12acc76d (0x93f6c04c12acc76e) (0x93f6c04c12acc76d) +// 0.00000000000000000000000000000000000000000000000000000 ** 3: 0x676eb3aa0a63236 != 0x676eb3aa0a63237 (0x676eb3aa0a63238) (0x676eb3aa0a63237) +// 0.00000000000000000000000007454937961610833261396029146 ** 3: 0x3047fcbe59481112 != 0x3047fcbe59481111 (0x3047fcbe59481110) (0x3047fcbe59481111) +// 0.00000000000000000000000000000000000003326770580987513 ** 3: 0x2896aaec8bb845c8 != 0x2896aaec8bb845c9 (0x2896aaec8bb845ca) (0x2896aaec8bb845c9) +// +// +// Test program modified to avoid bases with |abs(x) < 1| and large exponents. +// +// ```cpp +// // Skip over likely denormals. +// if (-1 < f && f < 0) { +// f -= 1; +// } else if (0 < f && f < 1) { +// f += 1; +// } +// +// f = std::fmod(f, 20); +// +// y = 3; +// ``` +// +// -11.40858423709869384765625000000000000000000000000000000 ** 3: 0xc0973392c88cadcc != 0xc0973392c88cadcd (0xc0973392c88cadce) (0xc0973392c88cadcd) +// 11.42477834224700927734375000000000000000000000000000000 ** 3: 0x40974ce701d58518 != 0x40974ce701d58519 (0x40974ce701d5851a) (0x40974ce701d58519) +// -11.46123231985238533070514677092432975769042968750000000 ** 3: 0xc097862ed0211e58 != 0xc097862ed0211e59 (0xc097862ed0211e5a) (0xc097862ed0211e59) +// -11.40183842182159423828125000000000000000000000000000000 ** 3: 0xc097290b23fe8cdc != 0xc097290b23fe8cdd (0xc097290b23fe8cde) (0xc097290b23fe8cdd) +// 2.87109172078278795936512324260547757148742675781250000 ** 3: 0x4037aab95517cdd0 != 0x4037aab95517cdcf (0x4037aab95517cdce) (0x4037aab95517cdcf) +// -0.72109144181013107299804687500000000000000000000000000 ** 3: 0xbfd7ff25d4fd46bc != 0xbfd7ff25d4fd46bd (0xbfd7ff25d4fd46be) (0xbfd7ff25d4fd46bd) +// 5.70116788148880004882812500000000000000000000000000000 ** 3: 0x406729d1c53687b4 != 0x406729d1c53687b5 (0x406729d1c53687b6) (0x406729d1c53687b5) +// -11.32285048566092200417187996208667755126953125000000000 ** 3: 0xc096aeac14d25c0e != 0xc096aeac14d25c0f (0xc096aeac14d25c10) (0xc096aeac14d25c0f) +// 1.41961999237537384033203125000000000000000000000000000 ** 3: 0x4006e34ea8957732 != 0x4006e34ea8957733 (0x4006e34ea8957734) (0x4006e34ea8957733) +// -11.52091628707762538397219032049179077148437500000000000 ** 3: 0xc097e4c12ab5e96e != 0xc097e4c12ab5e96f (0xc097e4c12ab5e970) (0xc097e4c12ab5e96f) +// -5.73415940999984741210937500000000000000000000000000000 ** 3: 0xc067915c3febbeba != 0xc067915c3febbebb (0xc067915c3febbebc) (0xc067915c3febbebb) +// 1.41478560105390638312883311300538480281829833984375000 ** 3: 0x4006a7a69b402738 != 0x4006a7a69b402737 (0x4006a7a69b402736) (0x4006a7a69b402737) +// -2.88328036665916442871093750000000000000000000000000000 ** 3: 0xc037f8371e1d17ce != 0xc037f8371e1d17cf (0xc037f8371e1d17d0) (0xc037f8371e1d17cf) +// 1.42408178602072932328326260176254436373710632324218750 ** 3: 0x40071aba43b3bcea != 0x40071aba43b3bceb (0x40071aba43b3bcec) (0x40071aba43b3bceb) +// 11.48128501093015074729919433593750000000000000000000000 ** 3: 0x4097a5d8fdac3954 != 0x4097a5d8fdac3955 (0x4097a5d8fdac3956) (0x4097a5d8fdac3955) +const testCases3 = [ + [196194373276.42089843750000000000000000000000000000000000000000000 , 3], + [17260025115986696435331651385474892363490876322742272.00000000000000000000000000000000000000000000000000000 , 3], + [-0.00000000000000000000000000000000000000000000000000000 , 3], + [2359506498398344427475761591701240715936602989985583832867274752.00000000000000000000000000000000000000000000000000000 , 3], + [22724457948673043906745552566513068013978508710758109286797554897659283949989408425377792.00000000000000000000000000000000000000000000000000000 , 3], + [-1024872849611580448634200763411882795753013248.00000000000000000000000000000000000000000000000000000 , 3], + [-918435268181356203923125447950336.00000000000000000000000000000000000000000000000000000 , 3], + [558545783776545344834655968246618719333738303286453207040.00000000000000000000000000000000000000000000000000000 , 3], + [0.00000000000000000000000000000000000000000000000000000 , 3], + [-0.00000000000261062225071774409619236799548496917242058 , 3], + [0.00000000000000000000000000000000000000000000012475377 , 3], + [-0.00000000000000000000000000000000000000000000000000000 , 3], + [0.00000000000000000000000000000000000000000000000000000 , 3], + [0.00000000000000000000000007454937961610833261396029146 , 3], + [0.00000000000000000000000000000000000003326770580987513 , 3], + + [-11.40858423709869384765625000000000000000000000000000000 , 3], + [11.42477834224700927734375000000000000000000000000000000 , 3], + [-11.46123231985238533070514677092432975769042968750000000 , 3], + [-11.40183842182159423828125000000000000000000000000000000 , 3], + [2.87109172078278795936512324260547757148742675781250000 , 3], + [-0.72109144181013107299804687500000000000000000000000000 , 3], + [5.70116788148880004882812500000000000000000000000000000 , 3], + [-11.32285048566092200417187996208667755126953125000000000 , 3], + [1.41961999237537384033203125000000000000000000000000000 , 3], + [-11.52091628707762538397219032049179077148437500000000000 , 3], + [-5.73415940999984741210937500000000000000000000000000000 , 3], + [1.41478560105390638312883311300538480281829833984375000 , 3], + [-2.88328036665916442871093750000000000000000000000000000 , 3], + [1.42408178602072932328326260176254436373710632324218750 , 3], + [11.48128501093015074729919433593750000000000000000000000 , 3], +]; + +// Ensure the error is less-or-equal to 2 ULP when compared to fdlibm. +// +// This can produce a larger error than std::pow, because we evaluate +// |x ** 3| as |(x * x) * x| to match Ion. +for (let [x, y] of testCases3) { + let actual = Math.pow(x, y); + let expected = fdlibm.pow(x, y); + let error = errorInULP(actual, expected); + assertEq(error <= 2, true, + `${x} ** ${y}: ${actual} (${toBits(actual).toString(16)}) != ${expected} (${toBits(expected).toString(16)})`); +} + +for (let [x, y] of testCases3) { + // Replace |y| with a constant to trigger Ion optimisations. + let actual = Math.pow(x, 3); + let expected = fdlibm.pow(x, y); + let error = errorInULP(actual, expected); + assertEq(error <= 2, true, + `${x} ** ${y}: ${actual} (${toBits(actual).toString(16)}) != ${expected} (${toBits(expected).toString(16)})`); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Math/shell.js b/js/src/tests/non262/Math/shell.js new file mode 100644 index 0000000000..7a64eccac9 --- /dev/null +++ b/js/src/tests/non262/Math/shell.js @@ -0,0 +1,74 @@ +// The nearest representable values to +1.0. +const ONE_PLUS_EPSILON = 1 + Math.pow(2, -52); // 0.9999999999999999 +const ONE_MINUS_EPSILON = 1 - Math.pow(2, -53); // 1.0000000000000002 + +{ + const fail = function (msg) { + var exc = new Error(msg); + try { + // Try to improve on exc.fileName and .lineNumber; leave exc.stack + // alone. We skip two frames: fail() and its caller, an assertX() + // function. + var frames = exc.stack.trim().split("\n"); + if (frames.length > 2) { + var m = /@([^@:]*):([0-9]+)$/.exec(frames[2]); + if (m) { + exc.fileName = m[1]; + exc.lineNumber = +m[2]; + } + } + } catch (ignore) { throw ignore;} + throw exc; + }; + + let ENDIAN; // 0 for little-endian, 1 for big-endian. + + // Return the difference between the IEEE 754 bit-patterns for a and b. + // + // This is meaningful when a and b are both finite and have the same + // sign. Then the following hold: + // + // * If a === b, then diff(a, b) === 0. + // + // * If a !== b, then diff(a, b) === 1 + the number of representable values + // between a and b. + // + const f = new Float64Array([0, 0]); + const u = new Uint32Array(f.buffer); + const diff = function (a, b) { + f[0] = a; + f[1] = b; + //print(u[1].toString(16) + u[0].toString(16) + " " + u[3].toString(16) + u[2].toString(16)); + return Math.abs((u[3-ENDIAN] - u[1-ENDIAN]) * 0x100000000 + u[2+ENDIAN] - u[0+ENDIAN]); + }; + + // Set ENDIAN to the platform's endianness. + ENDIAN = 0; // try little-endian first + if (diff(2, 4) === 0x100000) // exact wrong answer we'll get on a big-endian platform + ENDIAN = 1; + assertEq(diff(2,4), 0x10000000000000); + assertEq(diff(0, Number.MIN_VALUE), 1); + assertEq(diff(1, ONE_PLUS_EPSILON), 1); + assertEq(diff(1, ONE_MINUS_EPSILON), 1); + + var assertNear = function assertNear(a, b, tolerance=1) { + if (!Number.isFinite(b)) { + fail("second argument to assertNear (expected value) must be a finite number"); + } else if (Number.isNaN(a)) { + fail("got NaN, expected a number near " + b); + } else if (!Number.isFinite(a)) { + if (b * Math.sign(a) < Number.MAX_VALUE) + fail("got " + a + ", expected a number near " + b); + } else { + // When the two arguments do not have the same sign bit, diff() + // returns some huge number. So if b is positive or negative 0, + // make target the zero that has the same sign bit as a. + var target = b === 0 ? a * 0 : b; + var err = diff(a, target); + if (err > tolerance) { + fail("got " + a + ", expected a number near " + b + + " (relative error: " + err + ")"); + } + } + }; +} diff --git a/js/src/tests/non262/Math/sign.js b/js/src/tests/non262/Math/sign.js new file mode 100644 index 0000000000..5552dfc3d4 --- /dev/null +++ b/js/src/tests/non262/Math/sign.js @@ -0,0 +1,34 @@ +// If x is NaN, the result is NaN. +assertEq(Math.sign(NaN), NaN); + +// If x is −0, the result is −0. +assertEq(Math.sign(-0), -0); + +// If x is +0, the result is +0. +assertEq(Math.sign(+0), +0); + +// If x is negative and not −0, the result is −1. +assertEq(Math.sign(-Number.MIN_VALUE), -1); +assertEq(Math.sign(-Number.MAX_VALUE), -1); +assertEq(Math.sign(-Infinity), -1); + +for (var i = -1; i > -20; i--) + assertEq(Math.sign(i), -1); + +assertEq(Math.sign(-1e-300), -1); +assertEq(Math.sign(-0x80000000), -1); + +// If x is positive and not +0, the result is +1. +assertEq(Math.sign(Number.MIN_VALUE), +1); +assertEq(Math.sign(Number.MAX_VALUE), +1); +assertEq(Math.sign(Infinity), +1); + +for (var i = 1; i < 20; i++) + assertEq(Math.sign(i), +1); + +assertEq(Math.sign(+1e-300), +1); +assertEq(Math.sign(0x80000000), +1); +assertEq(Math.sign(0xffffffff), +1); + + +reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Math/sinh-approx.js b/js/src/tests/non262/Math/sinh-approx.js new file mode 100644 index 0000000000..15170dc666 --- /dev/null +++ b/js/src/tests/non262/Math/sinh-approx.js @@ -0,0 +1,297 @@ +for (var i = -20; i < 20; i++) + assertNear(Math.sinh(i), (Math.exp(i) - Math.exp(-i)) / 2); + +assertEq(Math.sinh(1000), Infinity); +assertEq(Math.sinh(Number.MAX_VALUE), Infinity); +assertNear(Math.sinh(1e-30), 1e-30); +assertNear(Math.sinh(1e-10), 1e-10); + +var sinh_data = [ + [-6.902103625349695, -497.1816406250001], + [-6.898143347143859, -495.21655273437517], + [-6.883664481302669, -488.0980224609375], + [-6.880304842490273, -486.46093750000006], + [-6.871561546509046, -482.2261962890624], + [-6.841973895837549, -468.167236328125], + [-6.836376331805493, -465.5539550781251], + [-6.833654100575195, -464.2883300781251], + [-6.8320816635009045, -463.55883789062483], + [-6.8108680173663085, -453.82861328125], + [-6.799689165151487, -448.78356933593756], + [-6.793579326246197, -446.0499267578126], + [-6.762510387544996, -432.4046630859374], + [-6.743225720989222, -424.14575195312506], + [-6.691758395994307, -402.86828613281244], + [-6.690743430063694, -402.4595947265625], + [-6.6596501292114505, -390.1383056640624], + [-6.652956360641761, -387.5355224609375], + [-6.635954365364267, -381.00231933593767], + [-6.619587562578274, -374.81726074218744], + [-6.617681179427804, -374.10339355468744], + [-6.614762741096185, -373.0131835937501], + [-6.60690568753706, -370.0938720703124], + [-6.591738907156094, -364.5230712890626], + [-6.583066984213974, -361.3756103515625], + [-6.573999516974134, -358.1136474609374], + [-6.553610904389896, -350.8861083984376], + [-6.553097634736138, -350.7060546875001], + [-6.538320325468202, -345.56164550781267], + [-6.529090881007076, -342.386962890625], + [-6.527791927233787, -341.94250488281256], + [-6.514383886150781, -337.38830566406244], + [-6.488639771044976, -328.8133544921875], + [-6.480460592697477, -326.13488769531256], + [-6.439759999015992, -313.1274414062499], + [-6.434927968512049, -311.61804199218744], + [-6.4082177348965725, -303.4047851562501], + [-6.369671035834965, -291.93200683593756], + [-6.362310184909175, -289.79101562500006], + [-6.356373428913315, -288.0756835937499], + [-6.337756593913614, -282.76220703125006], + [-6.32424009706147, -278.96594238281256], + [-6.314232650754295, -276.18811035156256], + [-6.290994606392703, -269.8439941406249], + [-6.240182555852785, -256.4750976562499], + [-6.2102675039793604, -248.9161987304687], + [-6.197335184435549, -245.71783447265628], + [-6.194021350132335, -244.90490722656253], + [-6.184119163536406, -242.4917602539062], + [-6.104686221071835, -223.97491455078116], + [-6.100669325836893, -223.07702636718747], + [-6.093582856519022, -221.50177001953122], + [-6.0598807500687935, -214.16101074218741], + [-6.0062142965262515, -202.97058105468741], + [-5.9923121073369945, -200.1683349609375], + [-5.981859446096083, -198.08691406249997], + [-5.9497792165852905, -191.83300781250006], + [-5.90509449745879, -183.44958496093747], + [-5.902097012275789, -182.90051269531256], + [-5.8144483910067954, -167.55175781250006], + [-5.786154254111214, -162.8773803710938], + [-5.765917008989405, -159.61425781250006], + [-5.703902219845274, -150.0162963867188], + [-5.6926689504460395, -148.34051513671872], + [-5.685206387751923, -147.23760986328122], + [-5.660572815631807, -143.6548461914062], + [-5.625516713960633, -138.70599365234375], + [-5.476934234171879, -119.55416870117192], + [-5.467584665632571, -118.4415588378906], + [-5.417932675603434, -112.70410156250004], + [-5.406565756574079, -111.43020629882811], + [-5.373195678988387, -107.77297973632808], + [-5.3723285712183735, -107.67956542968749], + [-5.348004040102253, -105.09179687499999], + [-5.31087758970896, -101.261474609375], + [-5.255348419702703, -95.79150390624997], + [-5.206986845736275, -91.26885986328122], + [-5.162914035396619, -87.33349609375003], + [-5.052952927749896, -78.23873901367186], + [-5.048772883924985, -77.91235351562501], + [-5.034848487644809, -76.83489990234378], + [-4.808269821238499, -61.25564575195312], + [-4.689849459883311, -54.413803100585945], + [-4.476720236388958, -43.96719360351561], + [-4.431216695067421, -42.01084899902342], + [-4.114720236218123, -30.60937499999999], + [-3.9785790831656023, -26.711166381835938], + [-3.9220215830953484, -25.24131774902344], + [-3.3770026324620295, -14.624359130859379], + [-3.214961448471211, -12.431087493896483], + [-3.021397455139021, -10.235607147216797], + [-2.937831931335705, -9.41094970703125], + [-1.267878515574959, -1.6359391212463381], + [1.6504814008555524e-12, 1.6504814008555524e-12], + [2.0654207510961697e-12, 2.0654207510961697e-12], + [6.933230031758164e-12, 6.933230031758164e-12], + [1.3351444949627478e-11, 1.3351444949627478e-11], + [1.6399812063916386e-11, 1.6399812063916386e-11], + [5.730159402528301e-11, 5.730159402528301e-11], + [1.113731329382972e-10, 1.113731329382972e-10], + [1.4214707189097453e-10, 1.4214707189097453e-10], + [3.8006320313144215e-10, 3.8006320313144215e-10], + [6.09162720266454e-10, 6.09162720266454e-10], + [1.0221641311147778e-9, 1.0221641311147778e-9], + [2.8819222563924995e-9, 2.8819222563924995e-9], + [4.7627768395841485e-9, 4.7627768395841485e-9], + [8.854133426439148e-9, 8.854133426439148e-9], + [2.305032609228874e-8, 2.3050326092288742e-8], + [5.939249092534734e-8, 5.9392490925347374e-8], + [1.1667648891489053e-7, 1.166764889148908e-7], + [2.379967440901942e-7, 2.3799674409019644e-7], + [4.6846594159431437e-7, 4.684659415943315e-7], + [9.382699772685088e-7, 9.382699772686465e-7], + [0.0000011039855962733358, 0.00000110398559627356], + [0.000003291776010877096, 0.0000032917760108830407], + [0.000007517213816683722, 0.00000751721381675452], + [0.000015114666893502755, 0.000015114666894078255], + [0.00002986399339999406, 0.00002986399340443313], + [0.000033870281179478836, 0.00003387028118595481], + [0.00009066011977069884, 0.00009066011989489198], + [0.00021949532498377364, 0.00021949532674625516], + [0.00043952149320897676, 0.00043952150736004114], + [0.0006333151408864353, 0.0006333151832222939], + [0.0011151230445582744, 0.001115123275667429], + [0.0019624658370807177, 0.001962467096745968], + [0.005553725496786973, 0.005553754046559334], + [0.008691018931968294, 0.008691128343343735], + [0.02992889492062484, 0.02993336319923401], + [0.05122020579778827, 0.05124260485172272], + [0.1117800293787828, 0.11201295256614685], + [0.23269806521543376, 0.23480379581451416], + [0.4721357117742938, 0.4898730516433716], + [0.694611571189336, 0.7518312931060792], + [1.2781607348262256, 1.6557407379150393], + [1.9917262343245115, 3.5958566665649414], + [2.009484184971722, 3.6627054214477544], + [2.128787712416205, 4.142845153808595], + [2.4846967934155475, 5.95706558227539], + [3.083125584533294, 10.890350341796875], + [4.002981567623351, 27.3714599609375], + [4.080736210902826, 29.586067199707028], + [4.120845430011113, 30.79753875732421], + [4.351258506393416, 38.78157043457031], + [4.540883728536112, 46.88148498535155], + [4.547981853382592, 47.21551513671875], + [4.5480891170767, 47.220581054687514], + [4.599728302509061, 49.72361755371096], + [4.8131842711857535, 61.557464599609396], + [4.910082619934558, 67.82162475585939], + [4.924747230639767, 68.82363891601564], + [4.993937439635391, 73.75466918945312], + [5.087099712053554, 80.95669555664065], + [5.1389346970196295, 85.26406860351562], + [5.138977285472121, 85.26770019531251], + [5.223879832616765, 92.82385253906247], + [5.241812789460327, 94.50357055664062], + [5.447141014648796, 116.04467773437499], + [5.511633288238573, 123.77554321289061], + [5.578681289305598, 132.3592529296875], + [5.633110296634631, 139.76330566406253], + [5.662701238627725, 143.96093750000003], + [5.678906941005323, 146.31298828124997], + [5.737214893086866, 155.0980224609375], + [5.739660763047893, 155.4778442382812], + [5.741349685869528, 155.74066162109372], + [5.790614371552514, 163.60546874999994], + [5.879059869096351, 178.73510742187494], + [5.884458728291027, 179.70269775390622], + [5.885109945587401, 179.8197631835937], + [5.893636014368936, 181.35949707031256], + [5.965274032538233, 194.82861328125003], + [5.967346683696556, 195.23284912109375], + [5.986843466070591, 199.07666015624994], + [6.019932686217942, 205.77423095703134], + [6.021252909681261, 206.0460815429687], + [6.037231102920489, 209.36480712890634], + [6.043606439928324, 210.70385742187506], + [6.06478541011501, 215.21398925781244], + [6.112974120371601, 225.83892822265622], + [6.117902255760311, 226.95465087890622], + [6.1433256889594094, 232.79864501953136], + [6.176483527820343, 240.64721679687503], + [6.186757751007361, 243.13244628906241], + [6.219667373726848, 251.26702880859372], + [6.229418088083555, 253.72906494140634], + [6.233184983047428, 254.68664550781241], + [6.243005711460192, 257.20019531250006], + [6.245102704489327, 257.74011230468744], + [6.260468857392134, 261.73120117187506], + [6.268152459140511, 263.74999999999994], + [6.2748285545831655, 265.5167236328125], + [6.305976070434008, 273.9171142578125], + [6.32399546069982, 278.8977050781249], + [6.324961403980197, 279.16723632812506], + [6.370613506132747, 292.20727539062494], + [6.375359978930309, 293.59753417968744], + [6.3766447200146, 293.9749755859376], + [6.380802563199264, 295.19982910156244], + [6.387824152942429, 297.27990722656244], + [6.390003820200831, 297.9285888671876], + [6.3905985680679, 298.10583496093744], + [6.397866642974941, 300.2803955078125], + [6.421725738171608, 307.5310058593751], + [6.423818963102848, 308.17541503906244], + [6.428865255911759, 309.7344970703124], + [6.443449261058927, 314.28479003906244], + [6.444844602076255, 314.7236328125], + [6.464094341970107, 320.84069824218756], + [6.465356699668166, 321.24597167968744], + [6.467400466944125, 321.90319824218756], + [6.472218114936839, 323.457763671875], + [6.4947499213823265, 330.8286132812501], + [6.507305446835735, 335.00854492187483], + [6.524202033435675, 340.71716308593756], + [6.546694993078936, 348.46777343749994], + [6.548591493378012, 349.1292724609374], + [6.613194950203132, 372.4288330078126], + [6.6247505436339065, 376.7574462890626], + [6.629181796246806, 378.43066406249994], + [6.6616087711302185, 390.9031982421874], + [6.698989091751707, 405.79187011718744], + [6.702857353572475, 407.3646240234375], + [6.717505881986416, 413.37585449218756], + [6.723197804327891, 415.73547363281256], + [6.726699007993023, 417.1936035156251], + [6.735483889307782, 420.87475585937483], + [6.755219602793124, 429.26354980468756], + [6.756366380816258, 429.75610351562506], + [6.766177290841293, 433.99316406250006], + [6.766217511883346, 434.01062011718767], + [6.780091308338912, 440.0739746093749], + [6.802889310303153, 450.22204589843744], + [6.813484439494547, 455.017578125], + [6.818196843455478, 457.16687011718744], + [6.818940201487998, 457.50683593749994], + [6.822833193143805, 459.29138183593756], + [6.82327083544577, 459.49243164062506], + [6.823817951018, 459.743896484375], + [6.834945773756887, 464.8884277343749], + [6.835113285253827, 464.96630859375017], + [6.840964582694129, 467.6949462890624], + [6.84346890521034, 468.86767578125017], + [6.847141429556457, 470.5927734375002], + [6.869243403190376, 481.10961914062483], + [6.882355637062964, 487.4595947265624], + [6.884531678915821, 488.5214843750001], + [6.89341643293734, 492.8812255859376], + [6.895822338701104, 494.06848144531233], + [6.900653737167637, 496.46130371093733], + [7.2670429692740965, 716.1540527343751], + [8.188647968122073, 1799.925781250001], + [8.872023251113289, 3564.8457031250014], + [9.566596912986167, 7139.869140625004], + [10.092554861905608, 12081.222656249996], + [10.728112113864427, 22810.24218749999], + [11.442480870715618, 46598.96875000003], + [12.28759157077177, 108493.37500000009], + [12.636950838344218, 153860.81249999988], + [13.327813723030063, 307019.4999999998], + [14.126778167009777, 682577.25], + [15.090269265334971, 1788919.000000001], + [15.835512291283944, 3769169], + [15.973721689554742, 4327820.000000002], + [16.910547205715446, 11044023.999999983], + [17.573132558903225, 21423208.000000004], + [18.649063156437965, 62828288.00000006], + [18.760110887365155, 70207360.00000012], + [19.547111966180875, 154231424.00000012], + [20.193967491567523, 294509055.9999997], + [21.484592263156223, 1070557183.9999999], + [22.088297141021556, 1957922816.0000024], + [22.780591462699917, 3912507392.0000005], + [23.401438520318692, 7279233024.000007], + [23.684949498080787, 9665245184.000017], + [24.5355829820426, 22627590144.000004], + [25.520740767599584, 60601991168.00004], + [26.31438890085422, 134018236416.00002], + [26.73876398039979, 204864946175.99973], + [27.06660583008718, 284346286080.00024], + [28.234874284944635, 914576637951.9989], + [28.78280496108106, 1581915832319.9973] +]; + +for (var [x, y] of sinh_data) + assertNear(Math.sinh(x), y); + +reportCompare(0, 0, "ok"); + diff --git a/js/src/tests/non262/Math/sinh-exact.js b/js/src/tests/non262/Math/sinh-exact.js new file mode 100644 index 0000000000..bfae1f7524 --- /dev/null +++ b/js/src/tests/non262/Math/sinh-exact.js @@ -0,0 +1,19 @@ +// Properties of Math.sinh that are guaranteed by the spec. + +// If x is NaN, the result is NaN. +assertEq(Math.sinh(NaN), NaN); + +// If x is +0, the result is +0. +assertEq(Math.sinh(+0), +0); + +// If x is −0, the result is −0. +assertEq(Math.sinh(-0), -0); + +// If x is +∞, the result is +∞. +assertEq(Math.sinh(Infinity), Infinity); + +// If x is −∞, the result is −∞. +assertEq(Math.sinh(-Infinity), -Infinity); + + +reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Math/tanh-approx.js b/js/src/tests/non262/Math/tanh-approx.js new file mode 100644 index 0000000000..252322a099 --- /dev/null +++ b/js/src/tests/non262/Math/tanh-approx.js @@ -0,0 +1,282 @@ +var sloppy_tolerance = 2; + +for (var i = -20; i < 20; i++) { + assertNear(Math.tanh(i), + (Math.exp(i) - Math.exp(-i)) / (Math.exp(i) + Math.exp(-i)), + sloppy_tolerance); +} + +assertEq(Math.tanh(1e300), 1); + +var tanh_data = [ + [-0.9999983310699463, -6.998237084679027], + [-0.9999978542327881, -6.87257975132917], + [-0.999992847442627, -6.2705920974657525], + [-0.9999861717224121, -5.940967614084813], + [-0.9999828338623047, -5.832855225378502], + [-0.9999399185180664, -5.20646301208756], + [-0.9998834133148193, -4.8749821841810785], + [-0.9998509883880615, -4.752279497280338], + [-0.9996016025543213, -4.260504202858904], + [-0.9993612766265869, -4.0244334353203115], + [-0.9989283084869385, -3.7655641082999236], + [-0.9969782829284668, -3.246782610980921], + [-0.9950058460235596, -2.9950671179940938], + [-0.9942638874053955, -2.9256242749609536], + [-0.990715742111206, -2.6839646283308363], + [-0.9903340339660645, -2.663723350226518], + [-0.9760982990264893, -2.207464998348322], + [-0.975830078125, -2.201817459680556], + [-0.9728245735168457, -2.1424542308291437], + [-0.9643559455871582, -2.0046686756020917], + [-0.9377224445343018, -1.7188337346177065], + [-0.9362406730651855, -1.7066940482565154], + [-0.9310147762298584, -1.6659543005533146], + [-0.9284839630126953, -1.6472838718760747], + [-0.9270248413085938, -1.6368067340881562], + [-0.9075665473937988, -1.5135473477311114], + [-0.897477388381958, -1.4590986086331497], + [-0.8920106887817383, -1.431681573516303], + [-0.8776559829711914, -1.365471286049011], + [-0.864722728729248, -1.3117705583444539], + [-0.8482067584991455, -1.249725893334944], + [-0.8056559562683105, -1.1145246028592257], + [-0.8048388957977295, -1.112200609756455], + [-0.7801985740661621, -1.0458778330822556], + [-0.7749934196472168, -1.032711173436253], + [-0.7619285583496094, -1.0007967281362184], + [-0.7504425048828125, -0.9739672824457072], + [-0.7495596408843994, -0.9719492983286864], + [-0.7481319904327393, -0.968698942014487], + [-0.7459518909454346, -0.9637657636705832], + [-0.7401137351989746, -0.9507308314464193], + [-0.7289731502532959, -0.9265325319867653], + [-0.7226788997650146, -0.9132299082876396], + [-0.7161557674407959, -0.8997082193533088], + [-0.7017018795013428, -0.8706453720344796], + [-0.7013418674468994, -0.86993650130945], + [-0.691054105758667, -0.8499705913361888], + [-0.6847054958343506, -0.837919455842005], + [-0.6838164329528809, -0.8362476144993315], + [-0.6747090816497803, -0.8193374156276964], + [-0.6575610637664795, -0.7885046044142132], + [-0.6522045135498047, -0.7791255597799839], + [-0.6261923313140869, -0.7351275788820003], + [-0.623173713684082, -0.7301771459970386], + [-0.6067488193511963, -0.7037597526130627], + [-0.5838055610656738, -0.6682166303197608], + [-0.579524040222168, -0.6617457665293066], + [-0.5760939121246338, -0.656596458857398], + [-0.5654678344726562, -0.6408350116350283], + [-0.5578761100769043, -0.6297442839791668], + [-0.5523209571838379, -0.6217149641475687], + [-0.5396339893341064, -0.6036390747171698], + [-0.5128989219665527, -0.5666556256064771], + [-0.5087778568267822, -0.5610793900942042], + [-0.4977825880050659, -0.546353950571504], + [-0.4913865327835083, -0.5378865967606703], + [-0.48976075649261475, -0.5357455496477738], + [-0.48493504524230957, -0.5294166456244711], + [-0.4479050636291504, -0.4820764946679979], + [-0.4461095333099365, -0.4798325976916711], + [-0.4429593086242676, -0.47590653371561276], + [-0.42827916145324707, -0.45778739362936793], + [-0.40590059757232666, -0.4306933608076879], + [-0.40029656887054443, -0.4240020382545707], + [-0.3961341381072998, -0.4190551379319939], + [-0.3836275339126587, -0.40430627175908734], + [-0.36686253547668457, -0.3847928551425507], + [-0.3657644987106323, -0.38352464227459343], + [-0.33507001399993896, -0.3485286317501442], + [-0.32572221755981445, -0.3380352468276522], + [-0.3191967010498047, -0.3307524237890151], + [-0.3000025749206543, -0.3095224337886503], + [-0.29665136337280273, -0.3058438250228025], + [-0.2944457530975342, -0.3034271164344305], + [-0.2872810363769531, -0.29560018347246825], + [-0.27738428115844727, -0.28484608203169437], + [-0.2390844225883484, -0.2438028008332661], + [-0.23685944080352783, -0.24144425169391517], + [-0.2253856658935547, -0.2293228153248168], + [-0.22283810377120972, -0.22664053064745143], + [-0.21552443504333496, -0.21895773601143995], + [-0.2153375744819641, -0.21876178107952995], + [-0.21016258001327515, -0.21334143320771737], + [-0.20250272750854492, -0.2053409277979887], + [-0.19156384468078613, -0.19396008474133075], + [-0.18251943588256836, -0.18458771439322938], + [-0.17464947700500488, -0.17645844608618066], + [-0.15646183490753174, -0.15775766677189154], + [-0.15580910444259644, -0.15708862621964176], + [-0.15365445613861084, -0.15488112515549593], + [-0.122499018907547, -0.12311733609904851], + [-0.1088167130947113, -0.10924929296737837], + [-0.08792558312416077, -0.08815322150790302], + [-0.08401328325271606, -0.08421178632314608], + [-0.06121261417865753, -0.06128924075509796], + [-0.05341699719429016, -0.05346789060550386], + [-0.05047759413719177, -0.05052053189238029], + [-0.02924579381942749, -0.029254136237332657], + [-0.02485968917608261, -0.02486481220617492], + [-0.020469173789024353, -0.02047203328100153], + [-0.01882001757621765, -0.018822240021756347], + [-0.016152501106262207, -0.016153906073109205], + [-0.0032715508714318275, -0.003271562543358962], + [1.6504814008555524e-12, 1.6504814008555524e-12], + [2.0654207510961697e-12, 2.0654207510961697e-12], + [6.933230031758164e-12, 6.933230031758164e-12], + [1.3351444949627478e-11, 1.3351444949627478e-11], + [1.6399812063916386e-11, 1.6399812063916386e-11], + [5.730159402528301e-11, 5.730159402528301e-11], + [1.113731329382972e-10, 1.113731329382972e-10], + [1.4214707189097453e-10, 1.4214707189097453e-10], + [3.8006320313144215e-10, 3.8006320313144215e-10], + [6.09162720266454e-10, 6.09162720266454e-10], + [1.0221641311147778e-9, 1.0221641311147778e-9], + [2.8819222563924995e-9, 2.8819222563924995e-9], + [4.7627768395841485e-9, 4.7627768395841485e-9], + [8.854133426439148e-9, 8.854133426439148e-9], + [2.3050326092288742e-8, 2.3050326092288745e-8], + [5.9392490925347374e-8, 5.939249092534745e-8], + [1.166764889148908e-7, 1.1667648891489133e-7], + [2.3799674409019644e-7, 2.3799674409020094e-7], + [4.684659415943315e-7, 4.684659415943658e-7], + [9.382699772686465e-7, 9.382699772689218e-7], + [0.00000110398559627356, 0.0000011039855962740086], + [0.0000032917760108830407, 0.0000032917760108949305], + [0.00000751721381675452, 0.000007517213816896115], + [0.000015114666894078255, 0.000015114666895229252], + [0.00002986399340443313, 0.00002986399341331128], + [0.00003387028118595481, 0.000033870281198906756], + [0.00009066011989489198, 0.00009066012014327826], + [0.00021949532674625516, 0.0002194953302712184], + [0.00043952150736004114, 0.0004395215356621756], + [0.0006333151832222939, 0.0006333152678940465], + [0.001115123275667429, 0.0011151237378863419], + [0.001962467096745968, 0.001962469616086656], + [0.005553754046559334, 0.005553811147953338], + [0.007324676960706711, 0.0073248079567425], + [0.008691128343343735, 0.008691347183450786], + [0.011912941932678223, 0.011913505535037906], + [0.02993336319923401, 0.029942308168570204], + [0.05124260485172272, 0.05128752666822782], + [0.05473744869232178, 0.05479221508125444], + [0.06158891320228577, 0.061666963819518306], + [0.09375360608100891, 0.09402975380882211], + [0.09442159533500671, 0.09470370926367391], + [0.09443172812461853, 0.09471393321406026], + [0.09943729639053345, 0.09976699249016487], + [0.11201295256614685, 0.11248498303558895], + [0.12310260534286499, 0.12373016402339168], + [0.13562965393066406, 0.13647060950861248], + [0.13763350248336792, 0.13851257866094746], + [0.14749455451965332, 0.14857829980464834], + [0.1618971824645996, 0.16333433166790448], + [0.17051106691360474, 0.17219298693637355], + [0.17051833868026733, 0.17220047646299907], + [0.18562912940979004, 0.18780647318150087], + [0.18898820877075195, 0.1912876932893582], + [0.23206615447998047, 0.23637212433914523], + [0.23480379581451416, 0.2392675448267427], + [0.2646920680999756, 0.27114729033023005], + [0.2794986963272095, 0.2871382059344433], + [0.28789305686950684, 0.2962673858386819], + [0.292596697807312, 0.30140373665239234], + [0.3101649284362793, 0.320727882769785], + [0.3109246492385864, 0.3215686893944558], + [0.31145012378692627, 0.3221505056451929], + [0.3271782398223877, 0.3396649461699478], + [0.3574345111846924, 0.37394153436545424], + [0.3593693971633911, 0.37616159223090223], + [0.35960352420806885, 0.37643046596933716], + [0.3626827001571655, 0.3799714809649667], + [0.38961827754974365, 0.4113499159905353], + [0.3904266357421875, 0.41230330080214], + [0.3981136083602905, 0.4214052375603139], + [0.411507248878479, 0.43742438709579096], + [0.4120509624481201, 0.43807911823743495], + [0.41868770122528076, 0.4460997186945703], + [0.42136549949645996, 0.4493511447897729], + [0.4516327381134033, 0.48674948990473677], + [0.4538639783859253, 0.4895560176112375], + [0.4655507802963257, 0.5043748446613433], + [0.48124635219573975, 0.5246050193978663], + [0.48621630668640137, 0.5310932154891663], + [0.4898730516433716, 0.5358932909903701], + [0.5024838447570801, 0.5526234425942533], + [0.5074074268341064, 0.5592320547729962], + [0.5093221664428711, 0.5618140818296767], + [0.5143489837646484, 0.5686253097655146], + [0.5154285430908203, 0.5700943191671631], + [0.5234100818634033, 0.5810250825991418], + [0.5274472236633301, 0.5866018515043636], + [0.5309803485870361, 0.5915094458340507], + [0.5477793216705322, 0.6152030999229688], + [0.5577394962310791, 0.6295459624918965], + [0.5582785606384277, 0.6303287742357745], + [0.5843560695648193, 0.6690521906099505], + [0.5871362686157227, 0.6732844960442398], + [0.5878911018371582, 0.6744372167164567], + [0.5903406143188477, 0.6781887236623534], + [0.5945003032684326, 0.684597775489552], + [0.5957975387573242, 0.6866065102131665], + [0.5961520671844482, 0.6871563252400655], + [0.6005008220672607, 0.6939300827887145], + [0.6150004863739014, 0.7169242329194352], + [0.6162893772125244, 0.7189998055497108], + [0.6194069385528564, 0.7240422748778544], + [0.6285066604614258, 0.7389438896054792], + [0.6293842792510986, 0.7403958734869583], + [0.6416172981262207, 0.7609178886018204], + [0.6424276828765869, 0.7622965466812235], + [0.6437420845031738, 0.7645378650643101], + [0.6468508243560791, 0.769864795178161], + [0.6615910530090332, 0.7956379107512945], + [0.669950008392334, 0.8106524185805045], + [0.6813662052154541, 0.8316597473423232], + [0.6968657970428467, 0.8611812790659296], + [0.6981887817382812, 0.8637579113749143], + [0.7447831630706787, 0.9611360201710216], + [0.7518312931060791, 0.9771540941752986], + [0.7534394264221191, 0.9808634133542229], + [0.7567856311798096, 0.9886489208209699], + [0.7817282676696777, 1.0497991719828956], + [0.8115026950836182, 1.1314141444187586], + [0.814647912979126, 1.1406947755584418], + [0.8266689777374268, 1.1775230833699681], + [0.8313877582550049, 1.1926138225701433], + [0.8343038558959961, 1.2021323323039612], + [0.8416652679443359, 1.2268570644335162], + [0.8584413528442383, 1.2873896671573652], + [0.8678996562957764, 1.3245040433929398], + [0.8679344654083252, 1.3246451309261607], + [0.8800599575042725, 1.3760334877782177], + [0.9003539085388184, 1.4740852961194106], + [0.9099440574645996, 1.5271990851861994], + [0.9142425060272217, 1.5527768948273004], + [0.9149219989776611, 1.556931837197936], + [0.9184908866882324, 1.5792896628381612], + [0.9188928604125977, 1.5818663359427627], + [0.919395923614502, 1.5851082843320008], + [0.9296839237213135, 1.6560555223295368], + [0.9298396110534668, 1.6572041418041492], + [0.9352962970733643, 1.6990986433619266], + [0.9376416206359863, 1.718164398807965], + [0.9410912990570068, 1.7475084077246632], + [0.962122917175293, 1.9737180163455101], + [0.9748215675354004, 2.1811227771083783], + [0.9769454002380371, 2.2257214499698255], + [0.985663890838623, 2.4654635601650536], + [0.9880380630493164, 2.5565869228142004], + [0.9928233623504639, 2.8132383539094192], + [1e-300, 1e-300], + [0.00001, 0.000010000000000333334], + [0.3, 0.3095196042031117], + [1e-30, 1e-30], + [1e-10, 1e-10], +]; + +for (var [x, y] of tanh_data) + assertNear(Math.tanh(y), x, sloppy_tolerance); + +reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Math/tanh-exact.js b/js/src/tests/non262/Math/tanh-exact.js new file mode 100644 index 0000000000..bfd9ac4def --- /dev/null +++ b/js/src/tests/non262/Math/tanh-exact.js @@ -0,0 +1,19 @@ +// Properties of Math.tanh that are guaranteed by the spec. + +// If x is NaN, the result is NaN. +assertEq(Math.tanh(NaN), NaN); + +// If x is +0, the result is +0. +assertEq(Math.tanh(+0), +0); + +// If x is −0, the result is −0. +assertEq(Math.tanh(-0), -0); + +// If x is +∞, the result is +1. +assertEq(Math.tanh(Number.POSITIVE_INFINITY), +1); + +// If x is −∞, the result is -1. +assertEq(Math.tanh(Number.NEGATIVE_INFINITY), -1); + + +reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Math/trunc.js b/js/src/tests/non262/Math/trunc.js new file mode 100644 index 0000000000..4cadfd9224 --- /dev/null +++ b/js/src/tests/non262/Math/trunc.js @@ -0,0 +1,50 @@ +// If x is NaN, the result is NaN. +assertEq(Math.trunc(NaN), NaN); + +// If x is −0, the result is −0. +assertEq(Math.trunc(-0), -0); + +// If x is +0, the result is +0. +assertEq(Math.trunc(+0), +0); + +// If x is +∞, the result is +∞. +assertEq(Math.trunc(Infinity), Infinity); + +// If x is −∞, the result is −∞. +assertEq(Math.trunc(-Infinity), -Infinity); + +// Other boundary cases. +var MAX_NONINTEGER_VALUE = 4503599627370495.5; +var TRUNC_MAX_NONINTEGER_VALUE = 4503599627370495; + +assertEq(Math.trunc(Number.MIN_VALUE), +0); +assertEq(Math.trunc(ONE_MINUS_EPSILON), +0); +assertEq(Math.trunc(ONE_PLUS_EPSILON), 1); +assertEq(Math.trunc(MAX_NONINTEGER_VALUE), TRUNC_MAX_NONINTEGER_VALUE); +assertEq(Math.trunc(Number.MAX_VALUE), Number.MAX_VALUE); + +assertEq(Math.trunc(-Number.MIN_VALUE), -0); +assertEq(Math.trunc(-ONE_MINUS_EPSILON), -0); +assertEq(Math.trunc(-ONE_PLUS_EPSILON), -1); +assertEq(Math.trunc(-MAX_NONINTEGER_VALUE), -TRUNC_MAX_NONINTEGER_VALUE); +assertEq(Math.trunc(-Number.MAX_VALUE), -Number.MAX_VALUE); + +// Other cases. +for (var i = 1, f = 1.1; i < 20; i++, f += 1.0) + assertEq(Math.trunc(f), i); + +for (var i = -1, f = -1.1; i > -20; i--, f -= 1.0) + assertEq(Math.trunc(f), i); + +assertEq(Math.trunc(1e40 + 0.5), 1e40); + +assertEq(Math.trunc(1e300), 1e300); +assertEq(Math.trunc(-1e300), -1e300); +assertEq(Math.trunc(1e-300), 0); +assertEq(Math.trunc(-1e-300), -0); + +assertEq(Math.trunc(+0.9999), +0); +assertEq(Math.trunc(-0.9999), -0); + + +reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Number/0x-without-following-hexdigits.js b/js/src/tests/non262/Number/0x-without-following-hexdigits.js new file mode 100644 index 0000000000..ffb329e5c8 --- /dev/null +++ b/js/src/tests/non262/Number/0x-without-following-hexdigits.js @@ -0,0 +1,30 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 582643; +var summary = "'0x' not followed by hex digits should be a syntax error"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +try +{ + eval("0x"); + throw new Error("didn't throw parsing 0x (with no subsequent hex digits)"); +} +catch (e) +{ + assertEq(e instanceof SyntaxError, true, + "bad exception thrown: " + e); +} + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Number/15.7.3.7-EPSILON.js b/js/src/tests/non262/Number/15.7.3.7-EPSILON.js new file mode 100644 index 0000000000..55e92ef1c0 --- /dev/null +++ b/js/src/tests/non262/Number/15.7.3.7-EPSILON.js @@ -0,0 +1,24 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 885798; +var summary = "ES6 (draft May 2013) 15.7.3.7 Number.EPSILON"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +// Test value +assertEq(Number.EPSILON, Math.pow(2, -52)); + +// Test property attributes +var descriptor = Object.getOwnPropertyDescriptor(Number, 'EPSILON'); +assertEq(descriptor.writable, false); +assertEq(descriptor.configurable, false); +assertEq(descriptor.enumerable, false); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Number/15.7.4.2.js b/js/src/tests/non262/Number/15.7.4.2.js new file mode 100644 index 0000000000..36443394cb --- /dev/null +++ b/js/src/tests/non262/Number/15.7.4.2.js @@ -0,0 +1,31 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +assertEq(raisesException(TypeError)('Number.prototype.toString.call(true)'), true); +assertEq(raisesException(TypeError)('Number.prototype.toString.call("")'), true); +assertEq(raisesException(TypeError)('Number.prototype.toString.call({})'), true); +assertEq(raisesException(TypeError)('Number.prototype.toString.call(null)'), true); +assertEq(raisesException(TypeError)('Number.prototype.toString.call([])'), true); +assertEq(raisesException(TypeError)('Number.prototype.toString.call(undefined)'), true); +assertEq(raisesException(TypeError)('Number.prototype.toString.call(new Boolean(true))'), true); + +assertEq(completesNormally('Number.prototype.toString.call(42)'), true); +assertEq(completesNormally('Number.prototype.toString.call(new Number(42))'), true); + +function testAround(middle) +{ + var range = 260; + var low = middle - range/2; + for (var i = 0; i < range; ++i) + assertEq(low + i, parseInt(String(low + i))); +} + +testAround(-Math.pow(2,32)); +testAround(-Math.pow(2,16)); +testAround(0); +testAround(+Math.pow(2,16)); +testAround(+Math.pow(2,32)); + +reportCompare(true, true); diff --git a/js/src/tests/non262/Number/20.1.2.10-MIN_SAFE_INTEGER.js b/js/src/tests/non262/Number/20.1.2.10-MIN_SAFE_INTEGER.js new file mode 100644 index 0000000000..8b96651ff2 --- /dev/null +++ b/js/src/tests/non262/Number/20.1.2.10-MIN_SAFE_INTEGER.js @@ -0,0 +1,26 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- + +var BUGNUMBER = 885798; +var summary = "ES6 (draft April 2014) 20.1.2.10 Number.MIN_SAFE_INTEGER"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +// Test value +assertEq(Number.MIN_SAFE_INTEGER, -(Math.pow(2, 53) - 1)); + +//Test property attributes +var descriptor = Object.getOwnPropertyDescriptor(Number, 'MIN_SAFE_INTEGER'); + +assertEq(descriptor.writable, false); +assertEq(descriptor.configurable, false); +assertEq(descriptor.enumerable, false); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Number/20.1.2.6-MAX_SAFE_INTEGER.js b/js/src/tests/non262/Number/20.1.2.6-MAX_SAFE_INTEGER.js new file mode 100644 index 0000000000..e3a2ddff1f --- /dev/null +++ b/js/src/tests/non262/Number/20.1.2.6-MAX_SAFE_INTEGER.js @@ -0,0 +1,26 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- + +var BUGNUMBER = 885798; +var summary = "ES6 (draft April 2014) 20.1.2.6 Number.MAX_SAFE_INTEGER"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +// Test value +assertEq(Number.MAX_SAFE_INTEGER, Math.pow(2, 53) - 1); + +//Test property attributes +var descriptor = Object.getOwnPropertyDescriptor(Number, 'MAX_SAFE_INTEGER'); + +assertEq(descriptor.writable, false); +assertEq(descriptor.configurable, false); +assertEq(descriptor.enumerable, false); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Number/20.1.3.2-toExponential.js b/js/src/tests/non262/Number/20.1.3.2-toExponential.js new file mode 100644 index 0000000000..f87c750df1 --- /dev/null +++ b/js/src/tests/non262/Number/20.1.3.2-toExponential.js @@ -0,0 +1,47 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- + +var BUGNUMBER = 818617; +var summary = "ECMAScript 2017 Draft ECMA-262 Section 20.1.3.2: Number.prototype.toExponential"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +// With NaN, fractionDigits out of range. +assertEq(Number.prototype.toExponential.call(NaN, 555), 'NaN'); + +// With NaN fractionDigits in range. +assertEq(Number.prototype.toExponential.call(NaN, 5), 'NaN'); + +// With Infinity, fractionDigits out of range. +assertEq(Number.prototype.toExponential.call(Infinity, 555), 'Infinity'); + +// With Infinity, fractionDigits in range. +assertEq(Number.prototype.toExponential.call(Infinity, 5), 'Infinity'); + +// With -Infinity, fractionDigits out of range. +assertEq(Number.prototype.toExponential.call(-Infinity, 555), '-Infinity'); + +// With -Infinity, fractionDigits in range. +assertEq(Number.prototype.toExponential.call(-Infinity, 5), '-Infinity'); + +// With NaN, function assigning a value. +let x = 10; +assertEq(Number.prototype.toExponential.call(NaN, { valueOf() { x = 20; return 1; } }), 'NaN'); +assertEq(x, 20); + +// With NaN, function throwing an exception. +assertThrows(() => Number.prototype.toExponential.call(NaN, { valueOf() { throw "hello"; } })); + +// Not a number throws TypeError +assertThrowsInstanceOf(() => Number.prototype.toExponential.call("Hello"), TypeError); + +if (typeof reportCompare === "function") { + reportCompare(true, true); +} + diff --git a/js/src/tests/non262/Number/20.1.3.2-toPrecision.js b/js/src/tests/non262/Number/20.1.3.2-toPrecision.js new file mode 100644 index 0000000000..5c98560445 --- /dev/null +++ b/js/src/tests/non262/Number/20.1.3.2-toPrecision.js @@ -0,0 +1,47 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- + +var BUGNUMBER = 818617; +var summary = "ECMAScript 2017 Draft ECMA-262 Section 20.1.3.5: Number.prototype.toPrecision"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +// With NaN, fractionDigits out of range. +assertEq(Number.prototype.toPrecision.call(NaN, 555), 'NaN'); + +// With NaN, fractionDigits in range. +assertEq(Number.prototype.toPrecision.call(NaN, 5), 'NaN'); + +// With Infinity, fractionDigits out of range. +assertEq(Number.prototype.toPrecision.call(Infinity, 555), 'Infinity'); + +// With Infinity, fractionDigits in range. +assertEq(Number.prototype.toPrecision.call(Infinity, 5), 'Infinity'); + +// With -Infinity, fractionDigits out of range. +assertEq(Number.prototype.toPrecision.call(-Infinity, 555), '-Infinity'); + +// With -Infinity, fractionDigits in range. +assertEq(Number.prototype.toPrecision.call(-Infinity, 5), '-Infinity'); + +// With NaN, function assigning a value. +let x = 10; +assertEq(Number.prototype.toPrecision.call(NaN, { valueOf() { x = 20; return 1; } }), 'NaN'); +assertEq(x, 20); + +// With NaN, function throwing an exception. +assertThrows(() => Number.prototype.toPrecision.call(NaN, { valueOf() { throw "hello"; } })); + +// Not a number throws TypeError +assertThrowsInstanceOf(() => Number.prototype.toPrecision.call("Hello"), TypeError); + +if (typeof reportCompare === "function") { + reportCompare(true, true); +} + diff --git a/js/src/tests/non262/Number/20.1.3.3-toFixed.js b/js/src/tests/non262/Number/20.1.3.3-toFixed.js new file mode 100644 index 0000000000..28b57ddaa2 --- /dev/null +++ b/js/src/tests/non262/Number/20.1.3.3-toFixed.js @@ -0,0 +1,17 @@ +/* + * Any copyright is dedicated to the Public Domain. + * https://creativecommons.org/publicdomain/zero/1.0/ + */ + +assertEq(Number.prototype.toFixed.call(-Infinity), "-Infinity"); +assertEq(Number.prototype.toFixed.call(Infinity), "Infinity"); +assertEq(Number.prototype.toFixed.call(NaN), "NaN"); + +assertThrowsInstanceOf(() => Number.prototype.toFixed.call(-Infinity, 555), RangeError); +assertThrowsInstanceOf(() => Number.prototype.toFixed.call(Infinity, 555), RangeError); +assertThrowsInstanceOf(() => Number.prototype.toFixed.call(NaN, 555), RangeError); + +assertThrowsInstanceOf(() => Number.prototype.toFixed.call("Hello"), TypeError); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Number/ToNumber.js b/js/src/tests/non262/Number/ToNumber.js new file mode 100644 index 0000000000..5716c8a000 --- /dev/null +++ b/js/src/tests/non262/Number/ToNumber.js @@ -0,0 +1,26 @@ +/* + * Any copyright is dedicated to the Public Domain. + * https://creativecommons.org/publicdomain/zero/1.0/ + */ + +assertEq(Number("0b11"), 3); +assertEq(Number("0B11"), 3); +assertEq(Number(" 0b11 "), 3); +assertEq(Number("0b12"), NaN); +assertEq(Number("-0b11"), NaN); +assertEq(+"0b11", 3); + +assertEq(Number("0o66"), 54); +assertEq(Number("0O66"), 54); +assertEq(Number(" 0o66 "), 54); +assertEq(Number("0o88"), NaN); +assertEq(Number("-0o66"), NaN); +assertEq(+"0o66", 54); + +if(typeof getSelfHostedValue === "function"){ + assertEq(getSelfHostedValue("ToNumber")("0b11"), 3); + assertEq(getSelfHostedValue("ToNumber")("0o66"), 54); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Number/browser.js b/js/src/tests/non262/Number/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Number/conversion-invalid-precision.js b/js/src/tests/non262/Number/conversion-invalid-precision.js new file mode 100644 index 0000000000..76c3a94d0a --- /dev/null +++ b/js/src/tests/non262/Number/conversion-invalid-precision.js @@ -0,0 +1,46 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommonn.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 795745; +var summary = + "Number.prototype.to* should throw a RangeError when passed a bad precision"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function test(method, prec) +{ + try + { + Number.prototype[method].call(0, prec); + throw "should have thrown"; + } + catch (e) + { + assertEq(e instanceof RangeError, true, + "expected RangeError for " + method + " with precision " + prec + + ", got " + e); + } +} + +test("toExponential", -32); +test("toFixed", -32); +test("toPrecision", -32); + +test("toExponential", 9999999); +test("toFixed", 9999999); +test("toPrecision", 9999999); + +test("toPrecision", 0); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Number/defaultvalue.js b/js/src/tests/non262/Number/defaultvalue.js new file mode 100644 index 0000000000..15bf021629 --- /dev/null +++ b/js/src/tests/non262/Number/defaultvalue.js @@ -0,0 +1,170 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommonn.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 645464; +var summary = + "[[DefaultValue]] behavior wrong for Number with overridden valueOf/toString"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + + +// equality + +var n = new Number(); +assertEq(n == 0, true); + +var n2 = new Number(); +n2.valueOf = function() { return 17; }; +assertEq(n2 == 17, true); + +var n3 = new Number(); +n3.toString = function() { return 42; }; +assertEq(n3 == 0, true); + +function testEquality() +{ + var n = new Number(); + assertEq(n == 0, true); + + var n2 = new Number(); + n2.valueOf = function() { return 17; }; + assertEq(n2 == 17, true); + + var n3 = new Number(); + n3.toString = function() { return 42; }; + assertEq(n3 == 0, true); +} +testEquality(); + + +// addition of Number to number + +var n = new Number(); +assertEq(n + 5, 5); + +var n2 = new Number(); +n2.toString = function() { return 9; }; +assertEq(n2 + 3, 3); + +var n3 = new Number(); +n3.valueOf = function() { return 17; }; +assertEq(n3 + 5, 22); + +function testNumberAddition() +{ + var n = new Number(); + assertEq(n + 5, 5); + + var n2 = new Number(); + n2.toString = function() { return 9; }; + assertEq(n2 + 3, 3); + + var n3 = new Number(); + n3.valueOf = function() { return 17; }; + assertEq(n3 + 5, 22); +} +testNumberAddition(); + + +// addition of Number to Number + +var n = new Number(); +assertEq(n + n, 0); + +var n2 = new Number(); +n2.toString = function() { return 5; }; +assertEq(n2 + n2, 0); + +var n3 = new Number(); +n3.valueOf = function() { return 8.5; }; +assertEq(n3 + n3, 17); + +function testNonNumberAddition() +{ + var n = new Number(); + assertEq(n + n, 0); + + var n2 = new Number(); + n2.toString = function() { return 5; }; + assertEq(n2 + n2, 0); + + var n3 = new Number(); + n3.valueOf = function() { return 8.5; }; + assertEq(n3 + n3, 17); +} +testNonNumberAddition(); + + +// Number as bracketed property name + +var obj = { 0: 17, 8: 42, 9: 8675309 }; + +var n = new Number(); +assertEq(obj[n], 17); + +var n2 = new Number(); +n2.valueOf = function() { return 8; } +assertEq(obj[n2], 17); + +var n3 = new Number(); +n3.toString = function() { return 9; }; +assertEq(obj[n3], 8675309); + +function testPropertyNameToNumber() +{ + var obj = { 0: 17, 8: 42, 9: 8675309 }; + + var n = new Number(); + assertEq(obj[n], 17); + + var n2 = new Number(); + n2.valueOf = function() { return 8; } + assertEq(obj[n2], 17); + + var n3 = new Number(); + n3.toString = function() { return 9; }; + assertEq(obj[n3], 8675309); +} +testPropertyNameToNumber(); + + +// Number as property name with |in| operator + +var n = new Number(); +assertEq(n in { 0: 5 }, true); + +var n2 = new Number(); +n2.toString = function() { return "baz"; }; +assertEq(n2 in { baz: 42 }, true); + +var n3 = new Number(); +n3.valueOf = function() { return "quux"; }; +assertEq(n3 in { 0: 17 }, true); + +function testInOperatorName() +{ + var n = new Number(); + assertEq(n in { 0: 5 }, true); + + var n2 = new Number(); + n2.toString = function() { return "baz"; }; + assertEq(n2 in { baz: 42 }, true); + + var n3 = new Number(); + n3.valueOf = function() { return "quux"; }; + assertEq(n3 in { 0: 17 }, true); +} +testInOperatorName(); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Number/isSafeInteger-01.js b/js/src/tests/non262/Number/isSafeInteger-01.js new file mode 100644 index 0000000000..d1a11cfe37 --- /dev/null +++ b/js/src/tests/non262/Number/isSafeInteger-01.js @@ -0,0 +1,40 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 1003764; +var summary = "ES6 (draft Draft May 22, 2014) ES6 20.1.2.5 Number.isSafeInteger(number)"; + +print(BUGNUMBER + ": " + summary); + +assertEq(Number.isSafeInteger.length, 1); + +assertEq(Number.isSafeInteger({}), false); +assertEq(Number.isSafeInteger(NaN), false); +assertEq(Number.isSafeInteger(+Infinity), false); +assertEq(Number.isSafeInteger(-Infinity), false); + +assertEq(Number.isSafeInteger(-1), true); +assertEq(Number.isSafeInteger(+0), true); +assertEq(Number.isSafeInteger(-0), true); +assertEq(Number.isSafeInteger(1), true); + +assertEq(Number.isSafeInteger(3.2), false); + +assertEq(Number.isSafeInteger(Math.pow(2, 53) - 2), true); +assertEq(Number.isSafeInteger(Math.pow(2, 53) - 1), true); +assertEq(Number.isSafeInteger(Math.pow(2, 53)), false); +assertEq(Number.isSafeInteger(Math.pow(2, 53) + 1), false); +assertEq(Number.isSafeInteger(Math.pow(2, 53) + 2), false); + +assertEq(Number.isSafeInteger(-Math.pow(2, 53) - 2), false); +assertEq(Number.isSafeInteger(-Math.pow(2, 53) - 1), false); +assertEq(Number.isSafeInteger(-Math.pow(2, 53)), false); +assertEq(Number.isSafeInteger(-Math.pow(2, 53) + 1), true); +assertEq(Number.isSafeInteger(-Math.pow(2, 53) + 2), true); + + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Number/numericSeparator.js b/js/src/tests/non262/Number/numericSeparator.js new file mode 100644 index 0000000000..46ebabc7ea --- /dev/null +++ b/js/src/tests/non262/Number/numericSeparator.js @@ -0,0 +1,10 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +assertThrowsInstanceOf(function() { eval('let a = 100_00_;'); }, SyntaxError); +assertThrowsInstanceOf(() => eval("let b = 10__;"), SyntaxError); +assertThrowsInstanceOf(() => eval("let b = 1._2;"), SyntaxError); + +if (typeof reportCompare === "function") + reportCompare(true, true); + diff --git a/js/src/tests/non262/Number/parseFloat-01.js b/js/src/tests/non262/Number/parseFloat-01.js new file mode 100644 index 0000000000..8c57e4e129 --- /dev/null +++ b/js/src/tests/non262/Number/parseFloat-01.js @@ -0,0 +1,27 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 886949; +var summary = "ES6 (draft May 2013) 15.7.3.10 Number.parseFloat(string)"; + +print(BUGNUMBER + ": " + summary); + +assertEq(Number.parseFloat("Infinity"), Infinity); +assertEq(Number.parseFloat("+Infinity"), Infinity); +assertEq(Number.parseFloat("-Infinity"), -Infinity); + +assertEq(Number.parseFloat("inf"), NaN); +assertEq(Number.parseFloat("Inf"), NaN); +assertEq(Number.parseFloat("infinity"), NaN); + +assertEq(Number.parseFloat("nan"), NaN); +assertEq(Number.parseFloat("NaN"), NaN); + +/* Number.parseFloat should be the same function object as global parseFloat. */ +assertEq(Number.parseFloat, parseFloat); + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Number/parseInt-01.js b/js/src/tests/non262/Number/parseInt-01.js new file mode 100644 index 0000000000..20bda18726 --- /dev/null +++ b/js/src/tests/non262/Number/parseInt-01.js @@ -0,0 +1,172 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 886949; +var summary = "ES6 (draft May 2013) 15.7.3.9 Number.parseInt(string, radix)"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var str, radix; +var upvar; + +/* 1. Let inputString be ToString(string). */ + +assertEq(Number.parseInt({ toString: function() { return "17" } }, 10), 17); + +upvar = 0; +str = { get toString() { upvar++; return function() { upvar++; return "12345"; } } }; +assertEq(Number.parseInt(str, 10), 12345); +assertEq(upvar, 2); + + +/* + * 2. Let S be a newly created substring of inputString consisting of the first + * character that is not a StrWhiteSpaceChar and all characters following + * that character. (In other words, remove leading white space.) + */ + +var ws = + ["\t", "\v", "\f", " ", "\xA0", "\uFEFF", + "\u2004", "\u3000", // a few Unicode whitespaces + "\r", "\n", "\u2028", "\u2029"]; + +str = "8675309"; +for (var i = 0, sz = ws.length; i < sz; i++) +{ + assertEq(Number.parseInt(ws[i] + str, 10), 8675309); + for (var j = 0, sz = ws.length; j < sz; j++) + { + assertEq(Number.parseInt(ws[i] + ws[j] + str, 10), 8675309, + ws[i].charCodeAt(0).toString(16) + ", " + + ws[j].charCodeAt(0).toString(16)); + } +} + + +/* + * 3. Let sign be 1. + * 4. If S is not empty and the first character of S is a minus sign -, let + * sign be −1. + */ +str = "5552368"; +assertEq(Number.parseInt("-" + str, 10), -Number.parseInt(str, 10)); +assertEq(Number.parseInt(" -" + str, 10), -Number.parseInt(str, 10)); +assertEq(Number.parseInt("-", 10), NaN); +assertEq(Number.parseInt("", 10), NaN); +assertEq(Number.parseInt("-0", 10), -0); + + +/* + * 5. If S is not empty and the first character of S is a plus sign + or a + * minus sign -, then remove the first character from S. + */ +assertEq(Number.parseInt("+12345", 10), 12345); +assertEq(Number.parseInt(" +12345", 10), 12345); +assertEq(Number.parseInt("-12345", 10), -12345); +assertEq(Number.parseInt(" -12345", 10), -12345); + + +/* + * 6. Let R = ToInt32(radix). + */ + +upvar = ""; +str = + { toString: function() { if (!upvar) upvar = "string"; return "42"; } }; +radix = + { toString: function() { if (!upvar) upvar = "radix"; return "10"; } }; + +assertEq(Number.parseInt(str, radix), 42); +assertEq(upvar, "string"); + +assertEq(Number.parseInt("123", null), 123); +assertEq(Number.parseInt("123", undefined), 123); +assertEq(Number.parseInt("123", NaN), 123); +assertEq(Number.parseInt("123", -0), 123); +assertEq(Number.parseInt("10", 72057594037927950), 16); +assertEq(Number.parseInt("10", -4294967292), 4); +assertEq(Number.parseInt("0x10", 1e308), 16); +assertEq(Number.parseInt("10", 1e308), 10); +assertEq(Number.parseInt("10", { valueOf: function() { return 16; } }), 16); + + +/* + * 7. Let stripPrefix be true. + * 8. If R ≠ 0, then + * a. If R < 2 or R > 36, then return NaN. + * b. If R ≠ 16, let stripPrefix be false. + * 9. Else, R = 0 + * a. Let R = 10. + * 10. If stripPrefix is true, then + * a. If the length of S is at least 2 and the first two characters of S + * are either “0x” or “0X”, then remove the first two characters from S and + * let R = 16. + */ +var vs = ["1", "51", "917", "2343", "99963"]; +for (var i = 0, sz = vs.length; i < sz; i++) + assertEq(Number.parseInt(vs[i], 0), Number.parseInt(vs[i], 10), "bad " + vs[i]); + +assertEq(Number.parseInt("0x10"), 16); +assertEq(Number.parseInt("0x10", 0), 16); +assertEq(Number.parseInt("0x10", 16), 16); +assertEq(Number.parseInt("0x10", 8), 0); +assertEq(Number.parseInt("-0x10", 16), -16); + +assertEq(Number.parseInt("5", 1), NaN); +assertEq(Number.parseInt("5", 37), NaN); +assertEq(Number.parseInt("5", { valueOf: function() { return -1; } }), NaN); + + +/* + * 11. If S contains any character that is not a radix-R digit, then let Z be + * the substring of S consisting of all characters before the first such + * character; otherwise, let Z be S. + * 12. If Z is empty, return NaN. + */ +assertEq(Number.parseInt(""), NaN); +assertEq(Number.parseInt("ohai"), NaN); +assertEq(Number.parseInt("0xohai"), NaN); +assertEq(Number.parseInt("-ohai"), NaN); +assertEq(Number.parseInt("+ohai"), NaN); +assertEq(Number.parseInt(" ohai"), NaN); + +assertEq(Number.parseInt("0xaohai"), 10); +assertEq(Number.parseInt("hohai", 18), 17); + + +/* + * 13. Let mathInt be the mathematical integer value that is represented by Z + * in radix-R notation, using the letters A-Z and a-z for digits with + * values 10 through 35. (However, if R is 10 and Z contains more than 20 + * significant digits, every significant digit after the 20th may be + * replaced by a 0 digit, at the option of the implementation; and if R is + * not 2, 4, 8, 10, 16, or 32, then mathInt may be an implementation- + * dependent approximation to the mathematical integer value that is + * represented by Z in radix-R notation.) + * 14. Let number be the Number value for mathInt. + * 15. Return sign × number. + */ +assertEq(Number.parseInt("ohai", 36), 1142154); +assertEq(Number.parseInt("0ohai", 36), 1142154); +assertEq(Number.parseInt("00ohai", 36), 1142154); +assertEq(Number.parseInt("A", 16), 10); +assertEq(Number.parseInt("0A", 16), 10); +assertEq(Number.parseInt("00A", 16), 10); +assertEq(Number.parseInt("A", 17), 10); +assertEq(Number.parseInt("0A", 17), 10); +assertEq(Number.parseInt("00A", 17), 10); + +/* Number.parseInt should be the same function object as global parseInt. */ +assertEq(Number.parseInt, parseInt); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Number/parseInt-default-to-decimal.js b/js/src/tests/non262/Number/parseInt-default-to-decimal.js new file mode 100644 index 0000000000..7049ef661b --- /dev/null +++ b/js/src/tests/non262/Number/parseInt-default-to-decimal.js @@ -0,0 +1,30 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 886949; +var summary = "ES6 (draft May 2013) 15.7.3.9 Number.parseInt(string, radix)." + + " Verify that Number.parseInt defaults to decimal."; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +assertEq(Number.parseInt("08"), 8); +assertEq(Number.parseInt("09"), 9); +assertEq(Number.parseInt("014"), 14); + +function strictParseInt(s) { "use strict"; return Number.parseInt(s); } + +assertEq(strictParseInt("08"), 8); +assertEq(strictParseInt("09"), 9); +assertEq(strictParseInt("014"), 14); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Number/regress-442242-01.js b/js/src/tests/non262/Number/regress-442242-01.js new file mode 100644 index 0000000000..a02f9511a0 --- /dev/null +++ b/js/src/tests/non262/Number/regress-442242-01.js @@ -0,0 +1,26 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 442242; +var summary = 'Do not assert: INT_FITS_IN_JSVAL(i)'; +var actual = 'No Crash'; +var expect = 'No Crash'; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + var i = 28800000; + -i; + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/Number/shell.js b/js/src/tests/non262/Number/shell.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Number/toExponential-values.js b/js/src/tests/non262/Number/toExponential-values.js new file mode 100644 index 0000000000..c626738461 --- /dev/null +++ b/js/src/tests/non262/Number/toExponential-values.js @@ -0,0 +1,118 @@ +let values = [ + [-0, undefined, "0e+0"], + [-0, 0, "0e+0"], + [-0, 1, "0.0e+0"], + [-0, 10, "0.0000000000e+0"], + [-0, 50, "0.00000000000000000000000000000000000000000000000000e+0"], + [-0, 100, "0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e+0"], + [0, undefined, "0e+0"], + [0, 0, "0e+0"], + [0, 1, "0.0e+0"], + [0, 10, "0.0000000000e+0"], + [0, 50, "0.00000000000000000000000000000000000000000000000000e+0"], + [0, 100, "0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e+0"], + [NaN, undefined, "NaN"], + [NaN, 0, "NaN"], + [NaN, 1, "NaN"], + [NaN, 10, "NaN"], + [NaN, 50, "NaN"], + [NaN, 100, "NaN"], + [Infinity, undefined, "Infinity"], + [Infinity, 0, "Infinity"], + [Infinity, 1, "Infinity"], + [Infinity, 10, "Infinity"], + [Infinity, 50, "Infinity"], + [Infinity, 100, "Infinity"], + [-Infinity, undefined, "-Infinity"], + [-Infinity, 0, "-Infinity"], + [-Infinity, 1, "-Infinity"], + [-Infinity, 10, "-Infinity"], + [-Infinity, 50, "-Infinity"], + [-Infinity, 100, "-Infinity"], + [3.141592653589793, undefined, "3.141592653589793e+0"], + [3.141592653589793, 0, "3e+0"], + [3.141592653589793, 1, "3.1e+0"], + [3.141592653589793, 10, "3.1415926536e+0"], + [3.141592653589793, 50, "3.14159265358979311599796346854418516159057617187500e+0"], + [3.141592653589793, 100, "3.1415926535897931159979634685441851615905761718750000000000000000000000000000000000000000000000000000e+0"], + [-1, undefined, "-1e+0"], + [-1, 0, "-1e+0"], + [-1, 1, "-1.0e+0"], + [-1, 10, "-1.0000000000e+0"], + [-1, 50, "-1.00000000000000000000000000000000000000000000000000e+0"], + [-1, 100, "-1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e+0"], + [1, undefined, "1e+0"], + [1, 0, "1e+0"], + [1, 1, "1.0e+0"], + [1, 10, "1.0000000000e+0"], + [1, 50, "1.00000000000000000000000000000000000000000000000000e+0"], + [1, 100, "1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e+0"], + [-123456.78, undefined, "-1.2345678e+5"], + [-123456.78, 0, "-1e+5"], + [-123456.78, 1, "-1.2e+5"], + [-123456.78, 10, "-1.2345678000e+5"], + [-123456.78, 50, "-1.23456779999999998835846781730651855468750000000000e+5"], + [-123456.78, 100, "-1.2345677999999999883584678173065185546875000000000000000000000000000000000000000000000000000000000000e+5"], + [123456.78, undefined, "1.2345678e+5"], + [123456.78, 0, "1e+5"], + [123456.78, 1, "1.2e+5"], + [123456.78, 10, "1.2345678000e+5"], + [123456.78, 50, "1.23456779999999998835846781730651855468750000000000e+5"], + [123456.78, 100, "1.2345677999999999883584678173065185546875000000000000000000000000000000000000000000000000000000000000e+5"], + [100000000000000000000, undefined, "1e+20"], + [100000000000000000000, 0, "1e+20"], + [100000000000000000000, 1, "1.0e+20"], + [100000000000000000000, 10, "1.0000000000e+20"], + [100000000000000000000, 50, "1.00000000000000000000000000000000000000000000000000e+20"], + [100000000000000000000, 100, "1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e+20"], + [1e+21, undefined, "1e+21"], + [1e+21, 0, "1e+21"], + [1e+21, 1, "1.0e+21"], + [1e+21, 10, "1.0000000000e+21"], + [1e+21, 50, "1.00000000000000000000000000000000000000000000000000e+21"], + [1e+21, 100, "1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e+21"], + [-100000000000000000000, undefined, "-1e+20"], + [-100000000000000000000, 0, "-1e+20"], + [-100000000000000000000, 1, "-1.0e+20"], + [-100000000000000000000, 10, "-1.0000000000e+20"], + [-100000000000000000000, 50, "-1.00000000000000000000000000000000000000000000000000e+20"], + [-100000000000000000000, 100, "-1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e+20"], + [-1e+21, undefined, "-1e+21"], + [-1e+21, 0, "-1e+21"], + [-1e+21, 1, "-1.0e+21"], + [-1e+21, 10, "-1.0000000000e+21"], + [-1e+21, 50, "-1.00000000000000000000000000000000000000000000000000e+21"], + [-1e+21, 100, "-1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e+21"], + [Number.MAX_VALUE, undefined, "1.7976931348623157e+308"], + [Number.MAX_VALUE, 0, "2e+308"], + [Number.MAX_VALUE, 1, "1.8e+308"], + [Number.MAX_VALUE, 10, "1.7976931349e+308"], + [Number.MAX_VALUE, 50, "1.79769313486231570814527423731704356798070567525845e+308"], + [Number.MAX_VALUE, 100, "1.7976931348623157081452742373170435679807056752584499659891747680315726078002853876058955863276687817e+308"], + [-Number.MAX_VALUE, undefined, "-1.7976931348623157e+308"], + [-Number.MAX_VALUE, 0, "-2e+308"], + [-Number.MAX_VALUE, 1, "-1.8e+308"], + [-Number.MAX_VALUE, 10, "-1.7976931349e+308"], + [-Number.MAX_VALUE, 50, "-1.79769313486231570814527423731704356798070567525845e+308"], + [-Number.MAX_VALUE, 100, "-1.7976931348623157081452742373170435679807056752584499659891747680315726078002853876058955863276687817e+308"], + [Number.MIN_VALUE, undefined, "5e-324"], + [Number.MIN_VALUE, 0, "5e-324"], + [Number.MIN_VALUE, 1, "4.9e-324"], + [Number.MIN_VALUE, 10, "4.9406564584e-324"], + [Number.MIN_VALUE, 50, "4.94065645841246544176568792868221372365059802614325e-324"], + [Number.MIN_VALUE, 100, "4.9406564584124654417656879286822137236505980261432476442558568250067550727020875186529983636163599238e-324"], + [-Number.MIN_VALUE, undefined, "-5e-324"], + [-Number.MIN_VALUE, 0, "-5e-324"], + [-Number.MIN_VALUE, 1, "-4.9e-324"], + [-Number.MIN_VALUE, 10, "-4.9406564584e-324"], + [-Number.MIN_VALUE, 50, "-4.94065645841246544176568792868221372365059802614325e-324"], + [-Number.MIN_VALUE, 100, "-4.9406564584124654417656879286822137236505980261432476442558568250067550727020875186529983636163599238e-324"], +]; + +for (let [val, prec, expected] of values) { + assertEq(Number.prototype.toExponential.call(val, prec), expected); +} + +if (typeof reportCompare === "function") { + reportCompare(true, true); +} diff --git a/js/src/tests/non262/Number/toFixed-values.js b/js/src/tests/non262/Number/toFixed-values.js new file mode 100644 index 0000000000..9b0b193948 --- /dev/null +++ b/js/src/tests/non262/Number/toFixed-values.js @@ -0,0 +1,118 @@ +let values = [ + [-0, undefined, "0"], + [-0, 0, "0"], + [-0, 1, "0.0"], + [-0, 10, "0.0000000000"], + [-0, 50, "0.00000000000000000000000000000000000000000000000000"], + [-0, 100, "0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"], + [0, undefined, "0"], + [0, 0, "0"], + [0, 1, "0.0"], + [0, 10, "0.0000000000"], + [0, 50, "0.00000000000000000000000000000000000000000000000000"], + [0, 100, "0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"], + [NaN, undefined, "NaN"], + [NaN, 0, "NaN"], + [NaN, 1, "NaN"], + [NaN, 10, "NaN"], + [NaN, 50, "NaN"], + [NaN, 100, "NaN"], + [Infinity, undefined, "Infinity"], + [Infinity, 0, "Infinity"], + [Infinity, 1, "Infinity"], + [Infinity, 10, "Infinity"], + [Infinity, 50, "Infinity"], + [Infinity, 100, "Infinity"], + [-Infinity, undefined, "-Infinity"], + [-Infinity, 0, "-Infinity"], + [-Infinity, 1, "-Infinity"], + [-Infinity, 10, "-Infinity"], + [-Infinity, 50, "-Infinity"], + [-Infinity, 100, "-Infinity"], + [3.141592653589793, undefined, "3"], + [3.141592653589793, 0, "3"], + [3.141592653589793, 1, "3.1"], + [3.141592653589793, 10, "3.1415926536"], + [3.141592653589793, 50, "3.14159265358979311599796346854418516159057617187500"], + [3.141592653589793, 100, "3.1415926535897931159979634685441851615905761718750000000000000000000000000000000000000000000000000000"], + [-1, undefined, "-1"], + [-1, 0, "-1"], + [-1, 1, "-1.0"], + [-1, 10, "-1.0000000000"], + [-1, 50, "-1.00000000000000000000000000000000000000000000000000"], + [-1, 100, "-1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"], + [1, undefined, "1"], + [1, 0, "1"], + [1, 1, "1.0"], + [1, 10, "1.0000000000"], + [1, 50, "1.00000000000000000000000000000000000000000000000000"], + [1, 100, "1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"], + [-123456.78, undefined, "-123457"], + [-123456.78, 0, "-123457"], + [-123456.78, 1, "-123456.8"], + [-123456.78, 10, "-123456.7800000000"], + [-123456.78, 50, "-123456.77999999999883584678173065185546875000000000000000"], + [-123456.78, 100, "-123456.7799999999988358467817306518554687500000000000000000000000000000000000000000000000000000000000000000"], + [123456.78, undefined, "123457"], + [123456.78, 0, "123457"], + [123456.78, 1, "123456.8"], + [123456.78, 10, "123456.7800000000"], + [123456.78, 50, "123456.77999999999883584678173065185546875000000000000000"], + [123456.78, 100, "123456.7799999999988358467817306518554687500000000000000000000000000000000000000000000000000000000000000000"], + [100000000000000000000, undefined, "100000000000000000000"], + [100000000000000000000, 0, "100000000000000000000"], + [100000000000000000000, 1, "100000000000000000000.0"], + [100000000000000000000, 10, "100000000000000000000.0000000000"], + [100000000000000000000, 50, "100000000000000000000.00000000000000000000000000000000000000000000000000"], + [100000000000000000000, 100, "100000000000000000000.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"], + [1e+21, undefined, "1e+21"], + [1e+21, 0, "1e+21"], + [1e+21, 1, "1e+21"], + [1e+21, 10, "1e+21"], + [1e+21, 50, "1e+21"], + [1e+21, 100, "1e+21"], + [-100000000000000000000, undefined, "-100000000000000000000"], + [-100000000000000000000, 0, "-100000000000000000000"], + [-100000000000000000000, 1, "-100000000000000000000.0"], + [-100000000000000000000, 10, "-100000000000000000000.0000000000"], + [-100000000000000000000, 50, "-100000000000000000000.00000000000000000000000000000000000000000000000000"], + [-100000000000000000000, 100, "-100000000000000000000.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"], + [-1e+21, undefined, "-1e+21"], + [-1e+21, 0, "-1e+21"], + [-1e+21, 1, "-1e+21"], + [-1e+21, 10, "-1e+21"], + [-1e+21, 50, "-1e+21"], + [-1e+21, 100, "-1e+21"], + [Number.MAX_VALUE, undefined, "1.7976931348623157e+308"], + [Number.MAX_VALUE, 0, "1.7976931348623157e+308"], + [Number.MAX_VALUE, 1, "1.7976931348623157e+308"], + [Number.MAX_VALUE, 10, "1.7976931348623157e+308"], + [Number.MAX_VALUE, 50, "1.7976931348623157e+308"], + [Number.MAX_VALUE, 100, "1.7976931348623157e+308"], + [-Number.MAX_VALUE, undefined, "-1.7976931348623157e+308"], + [-Number.MAX_VALUE, 0, "-1.7976931348623157e+308"], + [-Number.MAX_VALUE, 1, "-1.7976931348623157e+308"], + [-Number.MAX_VALUE, 10, "-1.7976931348623157e+308"], + [-Number.MAX_VALUE, 50, "-1.7976931348623157e+308"], + [-Number.MAX_VALUE, 100, "-1.7976931348623157e+308"], + [Number.MIN_VALUE, undefined, "0"], + [Number.MIN_VALUE, 0, "0"], + [Number.MIN_VALUE, 1, "0.0"], + [Number.MIN_VALUE, 10, "0.0000000000"], + [Number.MIN_VALUE, 50, "0.00000000000000000000000000000000000000000000000000"], + [Number.MIN_VALUE, 100, "0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"], + [-Number.MIN_VALUE, undefined, "-0"], + [-Number.MIN_VALUE, 0, "-0"], + [-Number.MIN_VALUE, 1, "-0.0"], + [-Number.MIN_VALUE, 10, "-0.0000000000"], + [-Number.MIN_VALUE, 50, "-0.00000000000000000000000000000000000000000000000000"], + [-Number.MIN_VALUE, 100, "-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"], +]; + +for (let [val, prec, expected] of values) { + assertEq(Number.prototype.toFixed.call(val, prec), expected); +} + +if (typeof reportCompare === "function") { + reportCompare(true, true); +} diff --git a/js/src/tests/non262/Number/toPrecision-values.js b/js/src/tests/non262/Number/toPrecision-values.js new file mode 100644 index 0000000000..fb59cf8597 --- /dev/null +++ b/js/src/tests/non262/Number/toPrecision-values.js @@ -0,0 +1,100 @@ +let values = [ + [-0, undefined, "0"], + [-0, 1, "0"], + [-0, 10, "0.000000000"], + [-0, 50, "0.0000000000000000000000000000000000000000000000000"], + [-0, 100, "0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"], + [0, undefined, "0"], + [0, 1, "0"], + [0, 10, "0.000000000"], + [0, 50, "0.0000000000000000000000000000000000000000000000000"], + [0, 100, "0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"], + [NaN, undefined, "NaN"], + [NaN, 1, "NaN"], + [NaN, 10, "NaN"], + [NaN, 50, "NaN"], + [NaN, 100, "NaN"], + [Infinity, undefined, "Infinity"], + [Infinity, 1, "Infinity"], + [Infinity, 10, "Infinity"], + [Infinity, 50, "Infinity"], + [Infinity, 100, "Infinity"], + [-Infinity, undefined, "-Infinity"], + [-Infinity, 1, "-Infinity"], + [-Infinity, 10, "-Infinity"], + [-Infinity, 50, "-Infinity"], + [-Infinity, 100, "-Infinity"], + [3.141592653589793, undefined, "3.141592653589793"], + [3.141592653589793, 1, "3"], + [3.141592653589793, 10, "3.141592654"], + [3.141592653589793, 50, "3.1415926535897931159979634685441851615905761718750"], + [3.141592653589793, 100, "3.141592653589793115997963468544185161590576171875000000000000000000000000000000000000000000000000000"], + [-1, undefined, "-1"], + [-1, 1, "-1"], + [-1, 10, "-1.000000000"], + [-1, 50, "-1.0000000000000000000000000000000000000000000000000"], + [-1, 100, "-1.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"], + [1, undefined, "1"], + [1, 1, "1"], + [1, 10, "1.000000000"], + [1, 50, "1.0000000000000000000000000000000000000000000000000"], + [1, 100, "1.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"], + [-123456.78, undefined, "-123456.78"], + [-123456.78, 1, "-1e+5"], + [-123456.78, 10, "-123456.7800"], + [-123456.78, 50, "-123456.77999999999883584678173065185546875000000000"], + [-123456.78, 100, "-123456.7799999999988358467817306518554687500000000000000000000000000000000000000000000000000000000000"], + [123456.78, undefined, "123456.78"], + [123456.78, 1, "1e+5"], + [123456.78, 10, "123456.7800"], + [123456.78, 50, "123456.77999999999883584678173065185546875000000000"], + [123456.78, 100, "123456.7799999999988358467817306518554687500000000000000000000000000000000000000000000000000000000000"], + [100000000000000000000, undefined, "100000000000000000000"], + [100000000000000000000, 1, "1e+20"], + [100000000000000000000, 10, "1.000000000e+20"], + [100000000000000000000, 50, "100000000000000000000.00000000000000000000000000000"], + [100000000000000000000, 100, "100000000000000000000.0000000000000000000000000000000000000000000000000000000000000000000000000000000"], + [1e+21, undefined, "1e+21"], + [1e+21, 1, "1e+21"], + [1e+21, 10, "1.000000000e+21"], + [1e+21, 50, "1000000000000000000000.0000000000000000000000000000"], + [1e+21, 100, "1000000000000000000000.000000000000000000000000000000000000000000000000000000000000000000000000000000"], + [-100000000000000000000, undefined, "-100000000000000000000"], + [-100000000000000000000, 1, "-1e+20"], + [-100000000000000000000, 10, "-1.000000000e+20"], + [-100000000000000000000, 50, "-100000000000000000000.00000000000000000000000000000"], + [-100000000000000000000, 100, "-100000000000000000000.0000000000000000000000000000000000000000000000000000000000000000000000000000000"], + [-1e+21, undefined, "-1e+21"], + [-1e+21, 1, "-1e+21"], + [-1e+21, 10, "-1.000000000e+21"], + [-1e+21, 50, "-1000000000000000000000.0000000000000000000000000000"], + [-1e+21, 100, "-1000000000000000000000.000000000000000000000000000000000000000000000000000000000000000000000000000000"], + [Number.MAX_VALUE, undefined, "1.7976931348623157e+308"], + [Number.MAX_VALUE, 1, "2e+308"], + [Number.MAX_VALUE, 10, "1.797693135e+308"], + [Number.MAX_VALUE, 50, "1.7976931348623157081452742373170435679807056752584e+308"], + [Number.MAX_VALUE, 100, "1.797693134862315708145274237317043567980705675258449965989174768031572607800285387605895586327668782e+308"], + [-Number.MAX_VALUE, undefined, "-1.7976931348623157e+308"], + [-Number.MAX_VALUE, 1, "-2e+308"], + [-Number.MAX_VALUE, 10, "-1.797693135e+308"], + [-Number.MAX_VALUE, 50, "-1.7976931348623157081452742373170435679807056752584e+308"], + [-Number.MAX_VALUE, 100, "-1.797693134862315708145274237317043567980705675258449965989174768031572607800285387605895586327668782e+308"], + [Number.MIN_VALUE, undefined, "5e-324"], + [Number.MIN_VALUE, 1, "5e-324"], + [Number.MIN_VALUE, 10, "4.940656458e-324"], + [Number.MIN_VALUE, 50, "4.9406564584124654417656879286822137236505980261432e-324"], + [Number.MIN_VALUE, 100, "4.940656458412465441765687928682213723650598026143247644255856825006755072702087518652998363616359924e-324"], + [-Number.MIN_VALUE, undefined, "-5e-324"], + [-Number.MIN_VALUE, 1, "-5e-324"], + [-Number.MIN_VALUE, 10, "-4.940656458e-324"], + [-Number.MIN_VALUE, 50, "-4.9406564584124654417656879286822137236505980261432e-324"], + [-Number.MIN_VALUE, 100, "-4.940656458412465441765687928682213723650598026143247644255856825006755072702087518652998363616359924e-324"], +]; + +for (let [val, prec, expected] of values) { + assertEq(Number.prototype.toPrecision.call(val, prec), expected); +} + +if (typeof reportCompare === "function") { + reportCompare(true, true); +} diff --git a/js/src/tests/non262/Number/toString-radix-handling.js b/js/src/tests/non262/Number/toString-radix-handling.js new file mode 100644 index 0000000000..dd91675a27 --- /dev/null +++ b/js/src/tests/non262/Number/toString-radix-handling.js @@ -0,0 +1,37 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommonn.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 647385; +var summary = + "Number.prototype.toString should use ToInteger on the radix and should " + + "throw a RangeError if the radix is bad"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function test(r) +{ + try + { + 5..toString(r); + throw "should have thrown"; + } + catch (e) + { + assertEq(e instanceof RangeError, true, "expected a RangeError, got " + e); + } +} +test(Math.pow(2, 32) + 10); +test(55); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Number/tonumber-string-hex.js b/js/src/tests/non262/Number/tonumber-string-hex.js new file mode 100644 index 0000000000..ed1e9b9dd4 --- /dev/null +++ b/js/src/tests/non262/Number/tonumber-string-hex.js @@ -0,0 +1,38 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommonn.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 872853; +var summary = 'Various tests of ToNumber(string), particularly +"0x" being NaN'; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +assertEq(+"0x", NaN); +assertEq(+"\t0x", NaN); +assertEq(+"0x\n", NaN); +assertEq(+"\n0x\t", NaN); +assertEq(+"0x0", 0); +assertEq(+"0xa", 10); +assertEq(+"0xff", 255); +assertEq(+"-0x", NaN); +assertEq(+"-0xa", NaN); +assertEq(+"-0xff", NaN); +assertEq(+"0xInfinity", NaN); +assertEq(+"+Infinity", Infinity); +assertEq(+"-Infinity", -Infinity); +assertEq(+"\t+Infinity", Infinity); +assertEq(+"-Infinity\n", -Infinity); +assertEq(+"+ Infinity", NaN); +assertEq(+"- Infinity", NaN); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/PrivateName/browser.js b/js/src/tests/non262/PrivateName/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/PrivateName/constructor-args.js b/js/src/tests/non262/PrivateName/constructor-args.js new file mode 100644 index 0000000000..970d809921 --- /dev/null +++ b/js/src/tests/non262/PrivateName/constructor-args.js @@ -0,0 +1,23 @@ +class A { + #x = "hello"; + constructor(o = this.#x) { + this.value = o; + } +}; + +var a = new A; +assertEq(a.value, "hello"); + + +class B extends A { + constructor() { + // Cannot access 'this' until super() called. + super(); + assertEq("value" in this, true); + assertEq(this.value, "hello"); + } +} + +var b = new B; + +if (typeof reportCompare === 'function') reportCompare(0, 0); diff --git a/js/src/tests/non262/PrivateName/error-locations.js b/js/src/tests/non262/PrivateName/error-locations.js new file mode 100644 index 0000000000..e91815ea81 --- /dev/null +++ b/js/src/tests/non262/PrivateName/error-locations.js @@ -0,0 +1,34 @@ +// |reftest| +function assertLineAndColumn(str, line, column) { + try { + eval(str); + throw 'didn\'t syntaxerror, bad.' + } catch (e) { + assertEq(e instanceof SyntaxError, true); + assertEq(e.lineNumber, line); + assertEq(e.columnNumber, column); + } +} + +assertLineAndColumn(`class A { g() { return this.#x; }}`, 1, 29); +// Make sure we're reporting the first error, if there are multiple, in class +// exit context; +assertLineAndColumn( + `class A { g() { return this.#x; } y() { return this.#z + this.#y; } }`, + 1, 29); +assertLineAndColumn(`this.#x`, 1, 6); +// Make sure we're reporting the first error, if there are multiple, in +// non-class context; +assertLineAndColumn(`this.#x; this.#y; this.#z`, 1, 6); + +assertLineAndColumn( + `class A { +g() { return this.#x; }}`, + 2, 19); +assertLineAndColumn( + `class A { + +g() { return this.#x; } y() { return this.#y; }}`, + 3, 19); + +if (typeof reportCompare === 'function') reportCompare(0, 0); diff --git a/js/src/tests/non262/PrivateName/error-outside-class.js b/js/src/tests/non262/PrivateName/error-outside-class.js new file mode 100644 index 0000000000..8ddb380872 --- /dev/null +++ b/js/src/tests/non262/PrivateName/error-outside-class.js @@ -0,0 +1,13 @@ + +// Can't reference a private field without an object +assertThrowsInstanceOf(() => eval('#x'), SyntaxError); + +// Can't reference a private field without an enclosing class +assertThrowsInstanceOf(() => eval('this.#x'), SyntaxError); + +// Can't reference a private field in a random function outside a class context +assertThrowsInstanceOf( + () => eval('function foo() { return this.#x'), SyntaxError); + + +if (typeof reportCompare === 'function') reportCompare(0, 0); diff --git a/js/src/tests/non262/PrivateName/home-object-when-preceded-by-computed-key.js b/js/src/tests/non262/PrivateName/home-object-when-preceded-by-computed-key.js new file mode 100644 index 0000000000..ef53a1304b --- /dev/null +++ b/js/src/tests/non262/PrivateName/home-object-when-preceded-by-computed-key.js @@ -0,0 +1,34 @@ +class Base { + m() { return "pass"; } + static m() { return "fail"; } +} + +var key = { + toString() { + return "computed"; + } +}; + +let obj1 = new class extends Base { + [key]() {} + + // Private method with a directly preceding method using a computed key led + // to assigning the wrong home object. + #m() { return super.m(); } + m() { return this.#m(); } +}; + +assertEq(obj1.m(), "pass"); + +let obj2 = new class extends Base { + // Same test as above, but this time preceded by a static method. + static [key]() {} + + #m() { return super.m(); } + m() { return this.#m(); } +}; + +assertEq(obj2.m(), "pass"); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/PrivateName/illegal-delete.js b/js/src/tests/non262/PrivateName/illegal-delete.js new file mode 100644 index 0000000000..464b7dd685 --- /dev/null +++ b/js/src/tests/non262/PrivateName/illegal-delete.js @@ -0,0 +1,94 @@ +// |reftest| skip-if(!xulRuntime.shell) -- needs newGlobal() + +class A { + #x = {a: 1}; + b = null; + es(s) { + eval(s); + } +} + +var a = new A; +a.b = new A; + +assertThrowsInstanceOf(() => a.es('delete this.#x'), SyntaxError); +assertThrowsInstanceOf(() => a.es('delete (this.#x)'), SyntaxError); +assertThrowsInstanceOf(() => a.es('delete this?.#x'), SyntaxError); +assertThrowsInstanceOf(() => a.es('delete this?.b.#x'), SyntaxError); +// Should be OK +a.es('delete (0, this.#x.a)') +a.es('delete this?.b.#x.a') + + +// Make sure the above works in a different context, with emphasis on +// lazy/syntax parsing. +function eval_and_report(str) { + var classTest = ` + class B { + #x = {a: 1}; + b = null; + test() { + ${str}; + } + } + var b = new B; + b.b = new B; + b.test(); + `; + + var str = ` + function f(run) { + if (run) { + ${classTest} + } + } + f(run)`; + + + var throws = []; + // Evalutate in a new global; has the advantage that it makes successes + // idempotent. + var g = newGlobal(); + g.run = false; + + try { + // The idea is that this is a full parse + evaluate(classTest, {global: g}); + } catch (e) { + throws.push(e); + } + + try { + // The idea is this is a lazy parse; however, fields currently + // disable lazy parsing, so right now + evaluate(str, {global: g}); + } catch (e) { + throws.push(e); + } + + return throws; +} + +function assertSyntaxError(str) { + var exceptions = eval_and_report(str); + assertEq(exceptions.length, 2); + for (var e of exceptions) { + assertEq(/SyntaxError/.test(e.name), true); + } +} + +function assertNoSyntaxError(str) { + var exceptions = eval_and_report(str); + assertEq(exceptions.length, 0); +} + +assertSyntaxError('delete this.#x'); +assertSyntaxError('delete (this.#x)'); +assertSyntaxError('delete this?.#x'); +assertSyntaxError('delete this?.b.#x'); +// Should be OK +assertNoSyntaxError('delete (0, this.#x.a)') +assertNoSyntaxError('delete this?.b.#x.a') + + +if (typeof reportCompare === 'function') reportCompare(0, 0); diff --git a/js/src/tests/non262/PrivateName/illegal-in-class-context.js b/js/src/tests/non262/PrivateName/illegal-in-class-context.js new file mode 100644 index 0000000000..85b34563ec --- /dev/null +++ b/js/src/tests/non262/PrivateName/illegal-in-class-context.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!xulRuntime.shell) + +assertThrowsInstanceOf(() => eval(`class A { #x; #x; }`), SyntaxError); + +// No computed private fields +assertThrowsInstanceOf( + () => eval(`var x = "foo"; class A { #[x] = 20; }`), SyntaxError); + +function assertThrowsWithMessage(f, msg) { + var fullmsg; + try { + f(); + } catch (exc) { + if (exc.message.normalize() === msg.normalize()) + return; + + fullmsg = `Assertion failed: expected message '${msg}', got '${exc.message}'`; + } + + if (fullmsg === undefined) + fullmsg = `Assertion failed: expected exception, no exception thrown`; + + throw new Error(fullmsg); +} + +assertThrowsWithMessage(() => eval(`class A { #x; h(o) { return !#x; }}`), + "invalid use of private name in unary expression without object reference"); +assertThrowsWithMessage(() => eval(`class A { #x; h(o) { return 1 + #x in o; }}`), + "invalid use of private name due to operator precedence"); + + +if (typeof reportCompare === 'function') reportCompare(0, 0); diff --git a/js/src/tests/non262/PrivateName/illegal-in-identifier-context.js b/js/src/tests/non262/PrivateName/illegal-in-identifier-context.js new file mode 100644 index 0000000000..e7e232bf69 --- /dev/null +++ b/js/src/tests/non262/PrivateName/illegal-in-identifier-context.js @@ -0,0 +1,45 @@ +// |reftest| skip-if(!xulRuntime.shell) + +// Private names can't appear in contexts where plain identifiers are expected. + +// Private names as binding identifiers. +assertThrowsInstanceOf(() => eval(`var #a;`), SyntaxError); +assertThrowsInstanceOf(() => eval(`let #a;`), SyntaxError); +assertThrowsInstanceOf(() => eval(`const #a = 0;`), SyntaxError); +assertThrowsInstanceOf(() => eval(`function #a(){}`), SyntaxError); +assertThrowsInstanceOf(() => eval(`function f(#a){}`), SyntaxError); + +// With escape sequences (leading and non-leading case). +assertThrowsInstanceOf(() => eval(String.raw`var #\u0061;`), SyntaxError); +assertThrowsInstanceOf(() => eval(String.raw`var #a\u0061;`), SyntaxError); +assertThrowsInstanceOf(() => eval(String.raw`let #\u0061;`), SyntaxError); +assertThrowsInstanceOf(() => eval(String.raw`let #a\u0061;`), SyntaxError); +assertThrowsInstanceOf(() => eval(String.raw`const #\u0061 = 0;`), SyntaxError); +assertThrowsInstanceOf(() => eval(String.raw`const #a\u0061 = 0;`), SyntaxError); +assertThrowsInstanceOf(() => eval(String.raw`function #\u0061(){}`), SyntaxError); +assertThrowsInstanceOf(() => eval(String.raw`function #a\u0061(){}`), SyntaxError); +assertThrowsInstanceOf(() => eval(String.raw`function f(#\u0061){}`), SyntaxError); +assertThrowsInstanceOf(() => eval(String.raw`function f(#a\u0061){}`), SyntaxError); + + +// Private names as label identifiers. +assertThrowsInstanceOf(() => eval(`#a: ;`), SyntaxError); + +// With escape sequences (leading and non-leading case). +assertThrowsInstanceOf(() => eval(String.raw`#\u0061: ;`), SyntaxError); +assertThrowsInstanceOf(() => eval(String.raw`#a\u0061: ;`), SyntaxError); + + +// Private names as identifier references. +assertThrowsInstanceOf(() => eval(`#a = 0;`), SyntaxError); +assertThrowsInstanceOf(() => eval(`typeof #a;`), SyntaxError); + +// With escape sequences (leading and non-leading case). +assertThrowsInstanceOf(() => eval(String.raw`#\u0061 = 0;`), SyntaxError); +assertThrowsInstanceOf(() => eval(String.raw`#a\u0061 = 0;`), SyntaxError); +assertThrowsInstanceOf(() => eval(String.raw`typeof #\u0061;`), SyntaxError); +assertThrowsInstanceOf(() => eval(String.raw`typeof #a\u0061;`), SyntaxError); + + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/PrivateName/illegal-in-object-context.js b/js/src/tests/non262/PrivateName/illegal-in-object-context.js new file mode 100644 index 0000000000..9cc1488376 --- /dev/null +++ b/js/src/tests/non262/PrivateName/illegal-in-object-context.js @@ -0,0 +1,14 @@ +// |reftest| skip-if(!xulRuntime.shell) + +// Private names aren't valid in object literals. + +assertThrowsInstanceOf(() => eval(`var o = {#a: 0};`), SyntaxError); +assertThrowsInstanceOf(() => eval(`var o = {#a};`), SyntaxError); +assertThrowsInstanceOf(() => eval(`var o = {#a(){}};`), SyntaxError); +assertThrowsInstanceOf(() => eval(`var o = {get #a(){}};`), SyntaxError); +assertThrowsInstanceOf(() => eval(`var o = {set #a(v){}};`), SyntaxError); +assertThrowsInstanceOf(() => eval(`var o = {*#a(v){}};`), SyntaxError); +assertThrowsInstanceOf(() => eval(`var o = {async #a(v){}};`), SyntaxError); +assertThrowsInstanceOf(() => eval(`var o = {async *#a(v){}};`), SyntaxError); + +if (typeof reportCompare === 'function') reportCompare(0, 0); diff --git a/js/src/tests/non262/PrivateName/lexical-presence.js b/js/src/tests/non262/PrivateName/lexical-presence.js new file mode 100644 index 0000000000..ce8588a0f1 --- /dev/null +++ b/js/src/tests/non262/PrivateName/lexical-presence.js @@ -0,0 +1,55 @@ +// |reftest| + +// Verify that private fields are enabled. +class A { + #x; +}; + +function assertThrowsSyntaxError(str) { + assertThrowsInstanceOf(() => eval(str), SyntaxError); // Direct Eval + assertThrowsInstanceOf(() => (1, eval)(str), SyntaxError); // Indirect Eval + assertThrowsInstanceOf(() => Function(str), SyntaxError); // Function +} + +assertThrowsSyntaxError(` + class B { + g() { + return this.#x; + } + }; +`); + +assertThrowsSyntaxError(` +with (new class A { #x; }) { + class B { + #y; + constructor() { return this.#x; } + } + } +`); + +// Make sure we don't create a generic binding for #x. +with (new class { + #x = 12; +}) { + assertEq('#x' in this, false); +} + +// Try to fetch a non-existing field using different +// compilation contexts +function assertNonExisting(fetchCode) { + source = `var X = class { + b() { + ${fetchCode} + } + } + var a = new X; + a.b()` + assertThrowsInstanceOf(() => eval(source), SyntaxError); +} + +assertNonExisting(`return eval("this.#x")"`); +assertNonExisting(`return (1,eval)("this.#x")`); +assertNonExisting(`var f = Function("this.#x"); return f();`); + +if (typeof reportCompare === 'function') reportCompare(0, 0); \ No newline at end of file diff --git a/js/src/tests/non262/PrivateName/modify-non-extensible.js b/js/src/tests/non262/PrivateName/modify-non-extensible.js new file mode 100644 index 0000000000..7e9af31895 --- /dev/null +++ b/js/src/tests/non262/PrivateName/modify-non-extensible.js @@ -0,0 +1,75 @@ +// |reftest| + +// Returns the argument in the constructor to allow stamping private fields into +// arbitrary objects. +class OverrideBase { + constructor(o) { + return o; + } +}; + +class A extends OverrideBase { + #a = 1; + g() { + return this.#a + } + + static gs(o) { + return o.#a; + } + static inca(obj) { + obj.#a++; + } +} + +var obj = {}; +Object.seal(obj); +new A(obj); // Add #a to obj, but not g. +assertEq('g' in obj, false); +assertEq(A.gs(obj), 1); +A.inca(obj); +assertEq(A.gs(obj), 2); + +// Ensure that the object remains non-extensible +obj.h = 'hi' +assertEq('h' in obj, false); + + +Object.freeze(obj); +A.inca(obj); // Despite being frozen, private names are modifiable. +assertEq(A.gs(obj), 3); +assertEq(Object.isFrozen(obj), true); + +var proxy = new Proxy({}, {}); +assertEq(Object.isFrozen(proxy), false); + +new A(proxy); +assertEq(A.gs(proxy), 1); + +// Note: this doesn't exercise the non-native object +// path in TestIntegrityLevel like you might expect. +// +// For that see below. +Object.freeze(proxy); +assertEq(Object.isFrozen(proxy), true); + +A.inca(proxy); +assertEq(A.gs(proxy), 2) + +var target = { a: 10 }; +Object.freeze(target); +new A(target); +assertEq(Object.isFrozen(target), true) + +var getOwnKeys = []; +var proxy = new Proxy(target, { + getOwnPropertyDescriptor: function (target, key) { + getOwnKeys.push(key); + return Reflect.getOwnPropertyDescriptor(target, key); + }, +}); + +Object.isFrozen(proxy); +assertEq(getOwnKeys.length, 1); + +if (typeof reportCompare === 'function') reportCompare(0, 0); diff --git a/js/src/tests/non262/PrivateName/names.js b/js/src/tests/non262/PrivateName/names.js new file mode 100644 index 0000000000..39d5128b2e --- /dev/null +++ b/js/src/tests/non262/PrivateName/names.js @@ -0,0 +1,30 @@ +// |reftest| +var C = class { + static #field = () => 'Test262'; + static field = () => 'Test262'; + #instance = () => 'Test262'; + instance = () => 'Test262'; + + static accessPrivateField() { + return this.#field; + } + + accessPrivateInstanceField() { + return this.#instance; + } + + static accessField() { + return this.field; + } + + accessInstanceField() { + return this.instance; + } +} +assertEq(C.accessPrivateField().name, '#field') +assertEq(C.accessField().name, 'field'); +var c = new C; +assertEq(c.accessPrivateInstanceField().name, '#instance'); +assertEq(c.accessInstanceField().name, 'instance'); + +if (typeof reportCompare === 'function') reportCompare(0, 0); diff --git a/js/src/tests/non262/PrivateName/nested-class-name-used.js b/js/src/tests/non262/PrivateName/nested-class-name-used.js new file mode 100644 index 0000000000..416a1aff36 --- /dev/null +++ b/js/src/tests/non262/PrivateName/nested-class-name-used.js @@ -0,0 +1,32 @@ +// |reftest| +// AllPrivateIdentifiersValid uses only lexical string names, not +// the dynamic private names; which means the below is not a syntax +// error but is instead a TypeError on access. + +class A { + #x = 10; + f() { + class B { + g() { + return this.#x; // note: #x isn't declared in this class, but + // the enclosing. + } + }; + this.y = new B; + } + constructor() { + this.f(); + } + g() { + return this.y.g(); + } +}; + +a = new A; +try { + a.g(); +} catch (e) { + assertEq(e instanceof TypeError, true); +} + +if (typeof reportCompare === 'function') reportCompare(0, 0); \ No newline at end of file diff --git a/js/src/tests/non262/PrivateName/not-iterable.js b/js/src/tests/non262/PrivateName/not-iterable.js new file mode 100644 index 0000000000..0e9a76f569 --- /dev/null +++ b/js/src/tests/non262/PrivateName/not-iterable.js @@ -0,0 +1,39 @@ +// |reftest| +// +// Ensure PrivateNames aren't iterable. + +class O { + #x = 123; + gx() { + return this.#x; + } +} +var o = new O; + +assertEq(o.gx(), 123); + +assertEq(Object.keys(o).length, 0); +assertEq(Object.getOwnPropertyNames(o).length, 0); +assertEq(Object.getOwnPropertySymbols(o).length, 0); +assertEq(Reflect.ownKeys(o).length, 0); + +var forIn = []; +for (var pk in o) { + forIn.push(pk); +} +assertEq(forIn.length, 0); + +// Proxy case +var proxy = new Proxy(o, {}); +assertEq(Object.keys(proxy).length, 0); +assertEq(Object.getOwnPropertyNames(proxy).length, 0); +assertEq(Object.getOwnPropertySymbols(proxy).length, 0); +assertEq(Reflect.ownKeys(proxy).length, 0); + +for (var pk in proxy) { + forIn.push(pk); +} +assertEq(forIn.length, 0); + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/PrivateName/parse-utf8-non-ascii-identifier.js b/js/src/tests/non262/PrivateName/parse-utf8-non-ascii-identifier.js new file mode 100644 index 0000000000..7f4b15f2dc --- /dev/null +++ b/js/src/tests/non262/PrivateName/parse-utf8-non-ascii-identifier.js @@ -0,0 +1,22 @@ +// Test that non-ASCII identifier names are correctly parsed in the Utf-8 parser. + +// Utf-8 encoding for U+05EF is (0xD7 0xAF), the first code unit isn't a valid +// Ascii ID_START code unit. +class NonAscii { + // U+05EF HEBREW YOD TRIANGLE + #ׯ; +} + +// Also check using Unicode escapes works. +class NonAsciiUnicodeEscape1 { + // U+05EF HEBREW YOD TRIANGLE + #\u05ef; +} + +class NonAsciiUnicodeEscape2 { + // U+05EF HEBREW YOD TRIANGLE + #\u{5ef}; +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/PrivateName/prototype-proxy.js b/js/src/tests/non262/PrivateName/prototype-proxy.js new file mode 100644 index 0000000000..55c8abab13 --- /dev/null +++ b/js/src/tests/non262/PrivateName/prototype-proxy.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty("wrapWithProto")) + +const o0 = {}; +const v2 = new Proxy(o0, o0); + +// v8 is a forwarding proxy with "prototype" behaviour; +// see the comment for mHasPrototype on BaseProxyHandler +// in Proxy.h. +// +// Private Fields don't interact with the hasPrototype +// behaviour (to minimize the overhead, and since private +// fields are always own properties). +const v8 = this.wrapWithProto(v2, {}); +function f9(a10) { + return v8; +} +class C11 extends f9 { + #b = 12; + static { + const v13 = new this(); + + const val = v8.#b; // Get + assertEq(val, 12); + + v8.#b = 0; // Set + assertEq(v8.#b, 0); + + assertEq(#b in v8, true); // HasOwn. + } +} + +if (typeof reportCompare === 'function') reportCompare(0, 0); diff --git a/js/src/tests/non262/PrivateName/proxy-1.js b/js/src/tests/non262/PrivateName/proxy-1.js new file mode 100644 index 0000000000..21f8f0ef08 --- /dev/null +++ b/js/src/tests/non262/PrivateName/proxy-1.js @@ -0,0 +1,21 @@ +// |reftest| + +class A { + #x = 10; + g() { + return this.#x; + } +}; + +var p = new Proxy(new A, {}); +var completed = false; +try { + p.g(); + completed = true; +} catch (e) { + assertEq(e instanceof TypeError, true); +} +assertEq(completed, false); + + +if (typeof reportCompare === 'function') reportCompare(0, 0); diff --git a/js/src/tests/non262/PrivateName/proxy-ccw.js b/js/src/tests/non262/PrivateName/proxy-ccw.js new file mode 100644 index 0000000000..94778489b6 --- /dev/null +++ b/js/src/tests/non262/PrivateName/proxy-ccw.js @@ -0,0 +1,66 @@ +// |reftest| + +// Validate CCWs and proxies +class Base { + constructor(o) { + return o; + } +} + +class A extends Base { + x1 = 12; + #x = 10; + static gx(o) { + return o.#x; + } + static sx(o, x) { + o.#x = x; + } + static hasx(o) { + try { + o.#x; + return true; + } catch { + return false; + } + } +} + + +var g = newGlobal({newCompartment: true}); +g.A = A; + +// cross_compartment_target is a cross compartment wrapper to an empty object. +var cross_compartment_target = g.eval('this.x = {}; this.x'); + +// #x gets stamped into the target of the CCW. +new A(cross_compartment_target); +assertEq(A.hasx(cross_compartment_target), true); + +// Can we update and read from this compartment? +assertEq(A.gx(cross_compartment_target), 10); +var o = {test: 12}; +A.sx(cross_compartment_target, o); +assertEq(A.gx(cross_compartment_target), o); + +// Can we read and update from the other compartment? +assertEq(g.eval('this.A.gx(this.x)'), o); +var y = g.eval('this.y = {test: 13}; this.A.sx(this.x, this.y); this.y'); +assertEq(g.eval('this.A.gx(this.x)'), y); +assertEq(A.gx(cross_compartment_target), y); + + +if (typeof nukeCCW === 'function') { + // Nuke the CCW. Now things should throw. + nukeCCW(cross_compartment_target); + var threw = true; + try { + A.gx(cross_compartment_target); + threw = false; + } catch (e) { + } + assertEq(threw, true); +} + + +if (typeof reportCompare === 'function') reportCompare(0, 0); \ No newline at end of file diff --git a/js/src/tests/non262/PrivateName/proxy-init-set.js b/js/src/tests/non262/PrivateName/proxy-init-set.js new file mode 100644 index 0000000000..bc78f50a09 --- /dev/null +++ b/js/src/tests/non262/PrivateName/proxy-init-set.js @@ -0,0 +1,74 @@ +// |reftest| +// Ensure that the distinction between Proxy Init and Proxy Set holds + +function assertThrowsTypeError(f) { + var type; + try { + f(); + } catch (ex) { + type = ex.name; + } + assertEq(type, 'TypeError'); +} + + + +var target = {}; +var p1 = new Proxy(target, {}); +var p2 = new Proxy(target, {}); + +class Base { + constructor(o) { + return o; + } +} + +class A extends Base { + #field = 10; + static gf(o) { + return o.#field; + } + static sf(o) { + o.#field = 15; + } +} + +class B extends Base { + #field = 25; + static gf(o) { + return o.#field; + } + static sf(o) { + o.#field = 20; + } +} + +// Verify field handling on the proxy we install it on. +new A(p1); +assertEq(A.gf(p1), 10); +A.sf(p1) +assertEq(A.gf(p1), 15); + +// Despite P1 being stamped with A's field, it shouldn't +// be sufficient to set B's field. +assertThrowsTypeError(() => B.sf(p1)); +assertThrowsTypeError(() => B.gf(p1)); +assertThrowsTypeError(() => B.sf(p1)); +new B(p1); +assertEq(B.gf(p1), 25); +B.sf(p1); +assertEq(B.gf(p1), 20); + +// A's field should't be on the target +assertThrowsTypeError(() => A.gf(target)); + +// Can't set the field, doesn't exist +assertThrowsTypeError(() => A.sf(p2)); + +// Definitely can't get the field, doesn't exist. +assertThrowsTypeError(() => A.gf(p2)); + +// Still should't be on the target. +assertThrowsTypeError(() => A.gf(target)); + +if (typeof reportCompare === 'function') reportCompare(0, 0); \ No newline at end of file diff --git a/js/src/tests/non262/PrivateName/read-private-eval.js b/js/src/tests/non262/PrivateName/read-private-eval.js new file mode 100644 index 0000000000..2c68e1c5d2 --- /dev/null +++ b/js/src/tests/non262/PrivateName/read-private-eval.js @@ -0,0 +1,13 @@ +// |reftest| + +class A { + #x = 14; + g() { + return eval('this.#x'); + } +} + +a = new A; +assertEq(a.g(), 14); + +if (typeof reportCompare === 'function') reportCompare(0, 0); \ No newline at end of file diff --git a/js/src/tests/non262/PrivateName/shell.js b/js/src/tests/non262/PrivateName/shell.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/PrivateName/unicode-names.js b/js/src/tests/non262/PrivateName/unicode-names.js new file mode 100644 index 0000000000..ff8d1fa2ff --- /dev/null +++ b/js/src/tests/non262/PrivateName/unicode-names.js @@ -0,0 +1,11 @@ +// |reftest| skip-if(!xulRuntime.shell) + +source = `class A { + // Ensure this name parses. Failure would be an InternalError: Buffer too + // small + #℘; +}`; + +Function(source); + +if (typeof reportCompare === 'function') reportCompare(0, 0); \ No newline at end of file diff --git a/js/src/tests/non262/Promise/allSettled.js b/js/src/tests/non262/Promise/allSettled.js new file mode 100644 index 0000000000..7644ea97a8 --- /dev/null +++ b/js/src/tests/non262/Promise/allSettled.js @@ -0,0 +1,86 @@ +// Smoke test for `Promise.allSettled`, test262 should cover the function in +// more detail. + +// Empty elements. +Promise.allSettled([]).then(v => { + assertDeepEq(v, []); +}); + +// Single element. +Promise.allSettled([Promise.resolve(0)]).then(v => { + assertDeepEq(v, [ + {"status": "fulfilled", "value": 0}, + ]); +}); +Promise.allSettled([Promise.reject(1)]).then(v => { + assertDeepEq(v, [ + {"status": "rejected", "reason": 1}, + ]); +}); + +// Multiple elements. +Promise.allSettled([Promise.resolve(1), Promise.resolve(2)]).then(v => { + assertDeepEq(v, [ + {"status": "fulfilled", "value": 1}, + {"status": "fulfilled", "value": 2}, + ]); +}); +Promise.allSettled([Promise.resolve(3), Promise.reject(4)]).then(v => { + assertDeepEq(v, [ + {"status": "fulfilled", "value": 3}, + {"status": "rejected", "reason": 4}, + ]); +}); +Promise.allSettled([Promise.reject(5), Promise.resolve(6)]).then(v => { + assertDeepEq(v, [ + {"status": "rejected", "reason": 5}, + {"status": "fulfilled", "value": 6}, + ]); +}); +Promise.allSettled([Promise.reject(7), Promise.reject(8)]).then(v => { + assertDeepEq(v, [ + {"status": "rejected", "reason": 7}, + {"status": "rejected", "reason": 8}, + ]); +}); + +// Cross-Realm tests. +// +// Note: When |g| is a cross-compartment global, Promise.allSettled creates +// the result array in |g|'s Realm. This doesn't follow the spec, but the code +// in js/src/builtin/Promise.cpp claims this is useful when the Promise +// compartment is less-privileged. This means for this test we can't use +// assertDeepEq below, because the result array may have the wrong prototype. +let g = newGlobal(); + +if (typeof isSameCompartment !== "function") { + var isSameCompartment = SpecialPowers.Cu.getJSTestingFunctions().isSameCompartment; +} + +// Test wrapping when neither Promise.allSettled element function is called. +Promise.allSettled.call(g.Promise, []).then(v => { + assertEq(isSameCompartment(v, g), true); + + assertEq(v.length, 0); +}); + +// Test wrapping in `Promise.allSettled Resolve Element Function`. +Promise.allSettled.call(g.Promise, [Promise.resolve(0)]).then(v => { + assertEq(isSameCompartment(v, g), true); + + assertEq(v.length, 1); + assertEq(v[0].status, "fulfilled"); + assertEq(v[0].value, 0); +}); + +// Test wrapping in `Promise.allSettled Reject Element Function`. +Promise.allSettled.call(g.Promise, [Promise.reject(0)]).then(v => { + assertEq(isSameCompartment(v, g), true); + + assertEq(v.length, 1); + assertEq(v[0].status, "rejected"); + assertEq(v[0].reason, 0); +}); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Promise/any-stack-overflow.js b/js/src/tests/non262/Promise/any-stack-overflow.js new file mode 100644 index 0000000000..8f3919e90a --- /dev/null +++ b/js/src/tests/non262/Promise/any-stack-overflow.js @@ -0,0 +1,14 @@ +// Bug 1646317 - Don't assert on stack overflow under Promise.any(). + +if ("ignoreUnhandledRejections" in this) { + ignoreUnhandledRejections(); +} + +Array.prototype[Symbol.iterator] = function*() { + let rejected = Promise.reject(0); + let p = Promise.any([rejected]); +} +new Set(Object.keys(this)); +new Set(Object.keys(this)); + +this.reportCompare && reportCompare(true, true); diff --git a/js/src/tests/non262/Promise/any-stack.js b/js/src/tests/non262/Promise/any-stack.js new file mode 100644 index 0000000000..dacb9e7f73 --- /dev/null +++ b/js/src/tests/non262/Promise/any-stack.js @@ -0,0 +1,69 @@ +// |reftest| skip-if(!xulRuntime.shell) -- needs async stack capture + +function toMessage(stack) { + // Provide the stack string in the error message for debugging. + return `[stack: ${stack.replace(/\n/g, "\\n")}]`; +} + +// Test when AggregateError isn't created from a Promise Job. +{ + let p = Promise.any([]); // line 10 + + p.then(v => { + reportCompare(0, 1, "expected error"); + }, e => { + assertEq(e.name, "AggregateError"); + var {stack} = e; + + assertEq(/^@.+any-stack.js:10/m.test(stack), true, toMessage(stack)); + }); +} + +// Same as above, but now with surrounding function context. +function testNoJobQueue() { + let p = Promise.any([]); // line 24 + + p.then(v => { + reportCompare(0, 1, "expected error"); + }, e => { + assertEq(e.name, "AggregateError"); + var {stack} = e; + + assertEq(/^testNoJobQueue@.+any-stack.js:24/m.test(stack), true, toMessage(stack)); + }); +} +testNoJobQueue(); + +// Test when AggregateError is created from a Promise Job. +{ + let rejected = Promise.reject(0); + let p = Promise.any([rejected]); // line 40 + + p.then(v => { + reportCompare(0, 1, "expected error"); + }, e => { + assertEq(e.name, "AggregateError"); + var {stack} = e; + + assertEq(/^Promise.any\*@.+any-stack.js:40/m.test(stack), true, toMessage(stack)); + }); +} + +// Same as above, but now with surrounding function context. +function testFromJobQueue() { + let rejected = Promise.reject(0); + let p = Promise.any([rejected]); // line 55 + + p.then(v => { + reportCompare(0, 1, "expected error"); + }, e => { + assertEq(e.name, "AggregateError"); + var {stack} = e; + + assertEq(/^Promise.any\*testFromJobQueue@.+any-stack.js:55/m.test(stack), true, toMessage(stack)); + }); +} +testFromJobQueue(); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Promise/any.js b/js/src/tests/non262/Promise/any.js new file mode 100644 index 0000000000..ff5e676bf5 --- /dev/null +++ b/js/src/tests/non262/Promise/any.js @@ -0,0 +1,76 @@ +// Smoke test for `Promise.any`, test262 should cover the function in +// more detail. + +function expectedError() { + reportCompare(true, false, "expected error"); +} + +// Empty elements. +Promise.any([]).then(expectedError, e => { + assertEq(e instanceof AggregateError, true); + assertEq(e.errors.length, 0); +}); + +// Single element. +Promise.any([Promise.resolve(0)]).then(v => { + assertEq(v, 0); +}); +Promise.any([Promise.reject(1)]).then(expectedError, e => { + assertEq(e instanceof AggregateError, true); + assertEq(e.errors.length, 1); + assertEq(e.errors[0], 1); +}); + +// Multiple elements. +Promise.any([Promise.resolve(1), Promise.resolve(2)]).then(v => { + assertEq(v, 1); +}); +Promise.any([Promise.resolve(3), Promise.reject(4)]).then(v => { + assertEq(v, 3); +}); +Promise.any([Promise.reject(5), Promise.resolve(6)]).then(v => { + assertEq(v, 6); +}); +Promise.any([Promise.reject(7), Promise.reject(8)]).then(expectedError, e => { + assertEq(e instanceof AggregateError, true); + assertEq(e.errors.length, 2); + assertEq(e.errors[0], 7); + assertEq(e.errors[1], 8); +}); + +// Cross-Realm tests. +// +// Note: When |g| is a cross-compartment global, Promise.any creates the errors +// array and the AggregateError in |g|'s Realm. This doesn't follow the spec, but +// the code in js/src/builtin/Promise.cpp claims this is useful when the Promise +// compartment is less-privileged. This means for this test we can't use +// assertDeepEq below, because the result array/error may have the wrong prototype. +let g = newGlobal(); + +if (typeof isSameCompartment !== "function") { + var isSameCompartment = SpecialPowers.Cu.getJSTestingFunctions().isSameCompartment; +} + +// Test wrapping when no `Promise.any Reject Element Function` is called. +Promise.any.call(g.Promise, []).then(expectedError, e => { + assertEq(e.name, "AggregateError"); + + assertEq(isSameCompartment(e, g), true); + assertEq(isSameCompartment(e.errors, g), true); + + assertEq(e.errors.length, 0); +}); + +// Test wrapping in `Promise.any Reject Element Function`. +Promise.any.call(g.Promise, [Promise.reject("err")]).then(expectedError, e => { + assertEq(e.name, "AggregateError"); + + assertEq(isSameCompartment(e, g), true); + assertEq(isSameCompartment(e.errors, g), true); + + assertEq(e.errors.length, 1); + assertEq(e.errors[0], "err"); +}); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Promise/browser.js b/js/src/tests/non262/Promise/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Promise/bug-1287334.js b/js/src/tests/non262/Promise/bug-1287334.js new file mode 100644 index 0000000000..19b9ca0aa0 --- /dev/null +++ b/js/src/tests/non262/Promise/bug-1287334.js @@ -0,0 +1,7 @@ +var promise = Promise.resolve(1); +var FakeCtor = function(exec){ exec(function(){}, function(){}); }; +Object.defineProperty(Promise, Symbol.species, {value: FakeCtor}); +// This just shouldn't crash. It does without bug 1287334 fixed. +promise.then(function(){}); + +this.reportCompare && reportCompare(true, true); diff --git a/js/src/tests/non262/Promise/bug-1288382.js b/js/src/tests/non262/Promise/bug-1288382.js new file mode 100644 index 0000000000..0a673a9caa --- /dev/null +++ b/js/src/tests/non262/Promise/bug-1288382.js @@ -0,0 +1,8 @@ +// This just shouldn't trigger a failed assert. +// It does without bug 1288382 fixed. +Promise.all.call(class { + constructor(exec){ exec(()=>{}, ()=>{}); } + static resolve() { return {then(){}}; } +}, [null]); + +this.reportCompare && reportCompare(true, true); diff --git a/js/src/tests/non262/Promise/bug-1289040.js b/js/src/tests/non262/Promise/bug-1289040.js new file mode 100644 index 0000000000..f5a9fd98e4 --- /dev/null +++ b/js/src/tests/non262/Promise/bug-1289040.js @@ -0,0 +1,8 @@ +var global = newGlobal(); +Promise.prototype.then = global.Promise.prototype.then; +p1 = new Promise(function f(r) { + r(1); +}); +p2 = p1.then(function g(){}); + +this.reportCompare && reportCompare(true,true); diff --git a/js/src/tests/non262/Promise/bug-1792196.js b/js/src/tests/non262/Promise/bug-1792196.js new file mode 100644 index 0000000000..946f5737de --- /dev/null +++ b/js/src/tests/non262/Promise/bug-1792196.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('settlePromiseNow')) + +function main() { + function v0(v1) { + throw "foobar"; + } + const v8 = new Promise(v0); + const v9 = v8.catch(); + const v11 = this.settlePromiseNow(v9); + function v12(v13) { + } + const v15 = new Promise(v11); + const v16 = v15.catch(v12); + gc(); +} +main(); + +this.reportCompare && reportCompare(true, true); diff --git a/js/src/tests/non262/Promise/dependent-promises.js b/js/src/tests/non262/Promise/dependent-promises.js new file mode 100644 index 0000000000..d0e2bfa8e8 --- /dev/null +++ b/js/src/tests/non262/Promise/dependent-promises.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!xulRuntime.shell) -- needs Debugger + +var g = newGlobal({newCompartment: true}); +var dbg = new Debugger(g); +var gw = dbg.addDebuggee(g); + +g.eval(` +var p = new Promise(() => {}); +p.name = "p"; +var q = p.then(); +q.name = "q"; +var r = p.then(null, () => {}); +r.name = "r"; +var s = Promise.all([p, q]); +s.name = "s"; +var t = Promise.race([r, s]); +t.name = "t"; +`); + +function getDependentNames(promise) { + return gw.makeDebuggeeValue(promise).promiseDependentPromises.map((p) => p.getOwnPropertyDescriptor('name').value); +} + +function arraysEqual(arr1, arr2, msg) { + assertEq(arr1.length, arr2.length, msg + ": length"); + for (var i = 0; i < arr1.length; ++i) { + assertEq(arr1[i], arr2[i], msg + ": [" + i + "]"); + } +} + +arraysEqual(getDependentNames(g.p), ["q", "r", "s"], "deps for p"); +arraysEqual(getDependentNames(g.q), ["s"], "deps for q"); +arraysEqual(getDependentNames(g.r), ["t"], "deps for r"); +arraysEqual(getDependentNames(g.s), ["t"], "deps for s"); + +this.reportCompare && reportCompare(true,true); diff --git a/js/src/tests/non262/Promise/enqueue-promise-reactions.js b/js/src/tests/non262/Promise/enqueue-promise-reactions.js new file mode 100644 index 0000000000..e7a6c2426e --- /dev/null +++ b/js/src/tests/non262/Promise/enqueue-promise-reactions.js @@ -0,0 +1,38 @@ +// |reftest| skip-if(!xulRuntime.shell) -- needs getSelfHostedValue and drainJobQueue + +function onResolved(val) { + result = 'resolved with ' + val; +} + +function onRejected(val) { + result = 'rejected with ' + val; +} + +// Replacing `Promise#then` shouldn't affect addPromiseReactions. +Promise.prototype.then = 1; + +// Replacing Promise@@species shouldn't affect addPromiseReactions. +Object.defineProperty(Promise, Symbol.species, { get: function(){} }); + +// Replacing `Promise` shouldn't affect addPromiseReactions. +let PromiseCtor = Promise; +Promise = {}; + +let result; +let res; +let rej; +let p = new PromiseCtor(function(res_, rej_) { res = res_; rej = rej_; }); + +addPromiseReactions(p, onResolved, onRejected); +res('foo'); +drainJobQueue(); +assertEq(result, 'resolved with foo') + +p = new PromiseCtor(function(res_, rej_) { res = res_; rej = rej_; }); + +addPromiseReactions(p, onResolved, onRejected); +rej('bar'); +drainJobQueue(); +assertEq(result, 'rejected with bar'); + +this.reportCompare && reportCompare(true,true); diff --git a/js/src/tests/non262/Promise/for-of-iterator-uses-getv.js b/js/src/tests/non262/Promise/for-of-iterator-uses-getv.js new file mode 100644 index 0000000000..28c888d7a3 --- /dev/null +++ b/js/src/tests/non262/Promise/for-of-iterator-uses-getv.js @@ -0,0 +1,25 @@ +"use strict"; // Use strict-mode to ensure |this| arguments aren't converted to objects. + +var emptyIterator = { + next() { + return {done: true}; + } +}; + +Object.defineProperty(Number.prototype, Symbol.iterator, { + configurable: true, + get() { + assertEq(typeof this, "number"); + return function() { + assertEq(typeof this, "number"); + return emptyIterator; + } + } +}); + +Promise.all(0); +Promise.allSettled(0); +Promise.race(0); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Promise/get-wait-for-all-promise.js b/js/src/tests/non262/Promise/get-wait-for-all-promise.js new file mode 100644 index 0000000000..69464ce08b --- /dev/null +++ b/js/src/tests/non262/Promise/get-wait-for-all-promise.js @@ -0,0 +1,60 @@ +// |reftest| skip-if(!xulRuntime.shell) -- needs getSelfHostedValue and drainJobQueue + +function onResolved(val) { + result = 'resolved with ' + val; +} + +function onRejected(val) { + result = 'rejected with ' + val; +} + +// Replacing `Promise#then` shouldn't affect getWaitForAllPromise. +let originalThen = Promise.prototype.then; +Promise.prototype.then = 1; + +// Replacing Promise[@@species] shouldn't affect getWaitForAllPromise. +Object.defineProperty(Promise, Symbol.species, { get: function(){} }); + +// Replacing `Promise` shouldn't affect getWaitForAllPromise. +let PromiseCtor = Promise; +Promise = {}; + +// Replacing Array[@@iterator] shouldn't affect getWaitForAllPromise. +Array.prototype[Symbol.iterator] = function(){}; + +let resolveFunctions = []; +let rejectFunctions = []; +let promises = []; +for (let i = 0; i < 3; i++) { + let p = new PromiseCtor(function(res_, rej_) { + resolveFunctions.push(res_); + rejectFunctions.push(rej_); + }); + promises.push(p); +} + +let allPromise = getWaitForAllPromise(promises); +let then = originalThen.call(allPromise, onResolved, onRejected); + +resolveFunctions.forEach((fun, i)=>fun(i)); +drainJobQueue(); + +assertEq(result, 'resolved with 0,1,2'); + +// Empty lists result in a promise resolved with an empty array. +result = undefined; +originalThen.call(getWaitForAllPromise([]), v=>(result = v)); +drainJobQueue(); +assertEq(result instanceof Array, true); +assertEq(result.length, 0); + +//Empty lists result in a promise resolved with an empty array. +result = undefined; +originalThen.call(getWaitForAllPromise([]), v=>(result = v)); + +drainJobQueue(); + +assertEq(result instanceof Array, true); +assertEq(result.length, 0); + +this.reportCompare && reportCompare(true,true); diff --git a/js/src/tests/non262/Promise/iterator-close.js b/js/src/tests/non262/Promise/iterator-close.js new file mode 100644 index 0000000000..b3127e87f2 --- /dev/null +++ b/js/src/tests/non262/Promise/iterator-close.js @@ -0,0 +1,234 @@ +// |reftest| skip-if(!xulRuntime.shell) -- needs drainJobQueue + +var BUGNUMBER = 1180306; +var summary = 'Promise.{all,race} should close iterator on error'; + +print(BUGNUMBER + ": " + summary); + +function test(ctor, props, { nextVal=undefined, + nextThrowVal=undefined, + modifier=undefined, + rejectReason=undefined, + rejectType=undefined, + closed=true }) { + function getIterable() { + let iterable = { + closed: false, + [Symbol.iterator]() { + let iterator = { + first: true, + next() { + if (this.first) { + this.first = false; + if (nextThrowVal) + throw nextThrowVal; + return nextVal; + } + return { value: undefined, done: true }; + }, + return() { + iterable.closed = true; + return {}; + } + }; + if (modifier) + modifier(iterator, iterable); + + return iterator; + } + }; + return iterable; + } + for (let prop of props) { + let iterable = getIterable(); + let e; + ctor[prop](iterable).catch(e_ => { e = e_; }); + drainJobQueue(); + if(rejectType) + assertEq(e instanceof rejectType, true); + else + assertEq(e, rejectReason); + assertEq(iterable.closed, closed); + } +} + +// == Error cases with close == + +// ES 2017 draft 25.4.4.1.1 step 6.i. +// ES 2017 draft 25.4.4.3.1 step 3.h. +class MyPromiseStaticResolveGetterThrows extends Promise { + static get resolve() { + throw "static resolve getter throws"; + } +}; +test(MyPromiseStaticResolveGetterThrows, ["all", "race"], { + nextVal: { value: Promise.resolve(1), done: false }, + rejectReason: "static resolve getter throws", + closed: false, +}); + +class MyPromiseStaticResolveThrows extends Promise { + static resolve() { + throw "static resolve throws"; + } +}; +test(MyPromiseStaticResolveThrows, ["all", "race"], { + nextVal: { value: Promise.resolve(1), done: false }, + rejectReason: "static resolve throws", + closed: true, +}); + +// ES 2017 draft 25.4.4.1.1 step 6.q. +// ES 2017 draft 25.4.4.3.1 step 3.i. +class MyPromiseThenGetterThrows extends Promise { + static resolve() { + return { + get then() { + throw "then getter throws"; + } + }; + } +}; +test(MyPromiseThenGetterThrows, ["all", "race"], { + nextVal: { value: Promise.resolve(1), done: false }, + rejectReason: "then getter throws", + closed: true, +}); + +class MyPromiseThenThrows extends Promise { + static resolve() { + return { + then() { + throw "then throws"; + } + }; + } +}; +test(MyPromiseThenThrows, ["all", "race"], { + nextVal: { value: Promise.resolve(1), done: false }, + rejectReason: "then throws", + closed: true, +}); + +// ES 2017 draft 7.4.6 step 3. +// if GetMethod fails, the thrown value should be used. +test(MyPromiseThenThrows, ["all", "race"], { + nextVal: { value: Promise.resolve(1), done: false }, + modifier: (iterator, iterable) => { + Object.defineProperty(iterator, "return", { + get: function() { + iterable.closed = true; + throw "return getter throws"; + } + }); + }, + rejectReason: "return getter throws", + closed: true, +}); +test(MyPromiseThenThrows, ["all", "race"], { + nextVal: { value: Promise.resolve(1), done: false }, + modifier: (iterator, iterable) => { + Object.defineProperty(iterator, "return", { + get: function() { + iterable.closed = true; + return "non object"; + } + }); + }, + rejectType: TypeError, + closed: true, +}); +test(MyPromiseThenThrows, ["all", "race"], { + nextVal: { value: Promise.resolve(1), done: false }, + modifier: (iterator, iterable) => { + Object.defineProperty(iterator, "return", { + get: function() { + iterable.closed = true; + // Non callable. + return {}; + } + }); + }, + rejectType: TypeError, + closed: true, +}); + +// ES 2017 draft 7.4.6 steps 6. +// if return method throws, the thrown value should be ignored. +test(MyPromiseThenThrows, ["all", "race"], { + nextVal: { value: Promise.resolve(1), done: false }, + modifier: (iterator, iterable) => { + iterator.return = function() { + iterable.closed = true; + throw "return throws"; + }; + }, + rejectReason: "then throws", + closed: true, +}); + +test(MyPromiseThenThrows, ["all", "race"], { + nextVal: { value: Promise.resolve(1), done: false }, + modifier: (iterator, iterable) => { + iterator.return = function() { + iterable.closed = true; + return "non object"; + }; + }, + rejectReason: "then throws", + closed: true, +}); + +// == Error cases without close == + +// ES 2017 draft 25.4.4.1.1 step 6.a. +test(Promise, ["all", "race"], { + nextThrowVal: "next throws", + rejectReason: "next throws", + closed: false, +}); + +test(Promise, ["all", "race"], { + nextVal: { value: {}, get done() { throw "done getter throws"; } }, + rejectReason: "done getter throws", + closed: false, +}); + +// ES 2017 draft 25.4.4.1.1 step 6.e. +test(Promise, ["all", "race"], { + nextVal: { get value() { throw "value getter throws"; }, done: false }, + rejectReason: "value getter throws", + closed: false, +}); + +// ES 2017 draft 25.4.4.1.1 step 6.d.iii.2. +let first = true; +class MyPromiseResolveThrows extends Promise { + constructor(executer) { + if (first) { + first = false; + super((resolve, reject) => { + executer(() => { + throw "resolve throws"; + }, reject); + }); + return; + } + super(executer); + } +}; +test(MyPromiseResolveThrows, ["all"], { + nextVal: { value: undefined, done: true }, + rejectReason: "resolve throws", + closed: false, +}); + +// == Successful cases == + +test(Promise, ["all", "race"], { + nextVal: { value: Promise.resolve(1), done: false }, + closed: false, +}); + +if (typeof reportCompare === 'function') + reportCompare(true, true); diff --git a/js/src/tests/non262/Promise/iterator-primitive.js b/js/src/tests/non262/Promise/iterator-primitive.js new file mode 100644 index 0000000000..cfc3a4ed32 --- /dev/null +++ b/js/src/tests/non262/Promise/iterator-primitive.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!xulRuntime.shell) -- needs drainJobQueue + +var BUGNUMBER = 1021835; +var summary = "Returning non-object from @@iterator should throw"; + +print(BUGNUMBER + ": " + summary); + +let primitives = [ + 1, + true, + undefined, + null, + "foo", + Symbol.iterator +]; + +for (let primitive of primitives) { + let arg = { + [Symbol.iterator]() { + return primitive; + } + }; + assertEventuallyThrows(Promise.all(arg), TypeError); + assertEventuallyThrows(Promise.race(arg), TypeError); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Promise/methods-non-enumerable.js b/js/src/tests/non262/Promise/methods-non-enumerable.js new file mode 100644 index 0000000000..ea2228894b --- /dev/null +++ b/js/src/tests/non262/Promise/methods-non-enumerable.js @@ -0,0 +1,4 @@ +assertEq(Object.keys(Promise).length, 0); +assertEq(Object.keys(Promise.prototype).length, 0); + +reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Promise/promise-all.js b/js/src/tests/non262/Promise/promise-all.js new file mode 100644 index 0000000000..3ae58fc384 --- /dev/null +++ b/js/src/tests/non262/Promise/promise-all.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!xulRuntime.shell) -- needs drainJobQueue + +let results = []; + +let p1 = new Promise(res=>res('result')) + .then(val=>{results.push('then ' + val); return 'first then rval';}) + .then(val=>{results.push('chained then with val: ' + val); return 'p1 then, then'}); + +let p2 = new Promise((res, rej)=>rej('rejection')) + .catch(val=> {results.push('catch ' + val); return results.length;}) + .then(val=>{results.push('then after catch with val: ' + val); return 'p2 catch, then'}, + val=>{throw new Error("mustn't be called")}); + +Promise.all([p1, p2]).then(res => results.push(res + '')); + +drainJobQueue(); + +assertEq(results.length, 5); +assertEq(results[0], 'then result'); +assertEq(results[1], 'catch rejection'); +assertEq(results[2], 'chained then with val: first then rval'); +assertEq(results[3], 'then after catch with val: 2'); +assertEq(results[4], 'p1 then, then,p2 catch, then'); + +this.reportCompare && reportCompare(true,true); diff --git a/js/src/tests/non262/Promise/promise-basics.js b/js/src/tests/non262/Promise/promise-basics.js new file mode 100644 index 0000000000..ad186537fe --- /dev/null +++ b/js/src/tests/non262/Promise/promise-basics.js @@ -0,0 +1,96 @@ +// |reftest| skip-if(!xulRuntime.shell) -- needs drainJobQueue + +let results = []; + +new Promise(res=>res('result')) + .then(val=>{results.push('then ' + val); return 'first then rval';}) + .then(val=>results.push('chained then with val: ' + val)); + +new Promise((res, rej)=>rej('rejection')) + .catch(val=>{results.push('catch ' + val); return results.length;}) + .then(val=>results.push('then after catch with val: ' + val), + val=>{throw new Error("mustn't be called")}); + +new Promise((res, rej)=> {res('result'); rej('rejection'); }) + .catch(val=>{throw new Error("mustn't be called");}) + .then(val=>results.push('then after resolve+reject with val: ' + val), + val=>{throw new Error("mustn't be called")}); + +new Promise((res, rej)=> { rej('rejection'); res('result'); }) + .catch(val=>{results.push('catch after reject+resolve with val: ' + val);}) + + +drainJobQueue(); + +assertEq(results.length, 6); +assertEq(results[0], 'then result'); +assertEq(results[1], 'catch rejection'); +assertEq(results[2], 'catch after reject+resolve with val: rejection'); +assertEq(results[3], 'chained then with val: first then rval'); +assertEq(results[4], 'then after catch with val: 2'); +assertEq(results[5], 'then after resolve+reject with val: result'); + +results = []; + +Promise.resolve('resolution').then(res=>results.push(res), + rej=>{ throw new Error("mustn't be called"); }); + +let thenCalled = false; +Promise.reject('rejection').then(_=>{thenCalled = true}, + rej=>results.push(rej)); + +drainJobQueue(); + +assertEq(thenCalled, false); +assertEq(results.length, 2); +assertEq(results[0], 'resolution'); +assertEq(results[1], 'rejection'); + + +function callback() {} + +// Calling the executor function with content functions shouldn't assert: +Promise.resolve.call(function(exec) { exec(callback, callback); }); +Promise.reject.call(function(exec) { exec(callback, callback); }); +Promise.all.call(function(exec) { exec(callback, callback); }); +Promise.race.call(function(exec) { exec(callback, callback); }); + +let resolveResult = undefined; +function resolveFun() {resolveResult = "resolveCalled";} +Promise.resolve.call(function(exec) { exec(resolveFun, callback); }); +assertEq(resolveResult, "resolveCalled"); + +let rejectResult = undefined; +function rejectFun() {rejectResult = "rejectCalled";} +Promise.reject.call(function(exec) { exec(callback, rejectFun); }); +assertEq(rejectResult, "rejectCalled"); + +// These should throw: +var wasCalled = false; +var hasThrown = false; +try { + // Calling the executor function twice, providing a resolve callback both times. + Promise.resolve.call(function(executor) { + wasCalled = true; + executor(callback, undefined); + executor(callback, callback); + }); +} catch (e) { + hasThrown = true; +} +assertEq(wasCalled, true); +assertEq(hasThrown, true); + +var hasThrown = false; +try { + // Calling the executor function twice, providing a reject callback both times. + Promise.resolve.call(function(executor) { + executor(undefined, callback); + executor(callback, callback); + }); +} catch (e) { + hasThrown = true; +} +assertEq(hasThrown, true); + +this.reportCompare && reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Promise/promise-rejection-tracking-optimized.js b/js/src/tests/non262/Promise/promise-rejection-tracking-optimized.js new file mode 100644 index 0000000000..c085b9dba8 --- /dev/null +++ b/js/src/tests/non262/Promise/promise-rejection-tracking-optimized.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!xulRuntime.shell) -- needs setPromiseRejectionTrackerCallback + +const UNHANDLED = 0; +const HANDLED = 1; + +let rejections = new Map(); +function rejectionTracker(promise, state) { + rejections.set(promise, state); +} +setPromiseRejectionTrackerCallback(rejectionTracker); + +// If the return value of then is not used, the promise object is optimized +// away, but if a rejection happens, the rejection should be notified. +Promise.resolve().then(() => { throw 1; }); +drainJobQueue(); + +assertEq(rejections.size, 1); + +let [[promise, state]] = rejections; +assertEq(state, UNHANDLED); + +let exc; +promise.catch(x => { exc = x; }); +drainJobQueue(); + +// we handled it after all +assertEq(rejections.get(promise), HANDLED); + +// the right exception was reported +assertEq(exc, 1); + +if (this.reportCompare) { + reportCompare(true,true); +} diff --git a/js/src/tests/non262/Promise/promise-rejection-tracking.js b/js/src/tests/non262/Promise/promise-rejection-tracking.js new file mode 100644 index 0000000000..a596fa6a99 --- /dev/null +++ b/js/src/tests/non262/Promise/promise-rejection-tracking.js @@ -0,0 +1,31 @@ +// |reftest| skip-if(!xulRuntime.shell) -- needs setPromiseRejectionTrackerCallback + +const UNHANDLED = 0; +const HANDLED = 1; + +let rejections = new Map(); +function rejectionTracker(promise, state) { + rejections.set(promise, state); +} +setPromiseRejectionTrackerCallback(rejectionTracker); + +// Unhandled rejections are tracked. +let reject; +let p = new Promise((res_, rej_) => (reject = rej_)); +assertEq(rejections.has(p), false); +reject('reason'); +assertEq(rejections.get(p), UNHANDLED); +// Later handling updates the tracking. +p.then(_=>_, _=>_); +assertEq(rejections.get(p), HANDLED); + +rejections.clear(); + +// Handled rejections aren't tracked at all. +p = new Promise((res_, rej_) => (reject = rej_)); +assertEq(rejections.has(p), false); +p.then(_=>_, _=>_); +reject('reason'); +assertEq(rejections.has(p), false); + +this.reportCompare && reportCompare(true,true); diff --git a/js/src/tests/non262/Promise/promise-species.js b/js/src/tests/non262/Promise/promise-species.js new file mode 100644 index 0000000000..52a4ecb632 --- /dev/null +++ b/js/src/tests/non262/Promise/promise-species.js @@ -0,0 +1,8 @@ +assertEq(Promise[Symbol.species], Promise); +let prop = Object.getOwnPropertyDescriptor(Promise, Symbol.species); +assertEq('get' in prop, true); +assertEq(typeof prop.get, 'function'); +assertEq('set' in prop, true); +assertEq(prop.set, undefined); + +reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Promise/promise-subclassing.js b/js/src/tests/non262/Promise/promise-subclassing.js new file mode 100644 index 0000000000..7232205f45 --- /dev/null +++ b/js/src/tests/non262/Promise/promise-subclassing.js @@ -0,0 +1,62 @@ +// |reftest| skip-if(!xulRuntime.shell) -- needs drainJobQueue + +let results = []; + +class SubPromise extends Promise { + constructor(executor) { + results.push('SubPromise ctor called'); + super(executor); + } + then(res, rej) { + results.push('SubPromise#then called'); + return intermediatePromise = super.then(res, rej); + } +} + +let subPromise = new SubPromise(function(res, rej) { + results.push('SubPromise ctor called executor'); + res('result'); +}); + +let intermediatePromise; +let allSubPromise = SubPromise.all([subPromise]); + +assertEq(subPromise instanceof SubPromise, true); +assertEq(allSubPromise instanceof SubPromise, true); +assertEq(intermediatePromise instanceof SubPromise, true); + +expected = [ +'SubPromise ctor called', +'SubPromise ctor called executor', +'SubPromise ctor called', +'SubPromise#then called', +'SubPromise ctor called', +]; + +assertEq(results.length, expected.length); +expected.forEach((expected,i) => assertEq(results[i], expected)); + +subPromise.then(val=>results.push('subPromise.then with val ' + val)); +allSubPromise.then(val=>results.push('allSubPromise.then with val ' + val)); + +expected.forEach((expected,i) => assertEq(results[i], expected)); +expected = expected.concat([ +'SubPromise#then called', +'SubPromise ctor called', +'SubPromise#then called', +'SubPromise ctor called', +]); + +assertEq(results.length, expected.length); +expected.forEach((expected,i) => assertEq(results[i], expected)); + +drainJobQueue(); + +expected = expected.concat([ +'subPromise.then with val result', +'allSubPromise.then with val result', +]); + +assertEq(results.length, expected.length); + +this.reportCompare && reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Promise/self-resolve.js b/js/src/tests/non262/Promise/self-resolve.js new file mode 100644 index 0000000000..53f76a99ce --- /dev/null +++ b/js/src/tests/non262/Promise/self-resolve.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!xulRuntime.shell) -- needs drainJobQueue + +// Resolve Promise with itself by directly calling the "Promise Resolve Function". +let resolve; +let promise = new Promise(function(x) { resolve = x; }); +resolve(promise) + +let results = []; +promise.then(res => assertEq(true, false, "not reached")).catch(res => { + assertEq(res instanceof TypeError, true); + results.push("rejected"); +}); + +drainJobQueue() + +assertEq(results.length, 1); +assertEq(results[0], "rejected"); + + +// Resolve Promise with itself when the "Promise Resolve Function" is called +// from (the fast path in) PromiseReactionJob. +results = []; + +promise = new Promise(x => { resolve = x; }); +let promise2 = promise.then(() => promise2); + +promise2.then(() => assertEq(true, false, "not reached"), res => { + assertEq(res instanceof TypeError, true); + results.push("rejected"); +}); + +resolve(); + +drainJobQueue(); + +assertEq(results.length, 1); +assertEq(results[0], "rejected"); + + +this.reportCompare && reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Promise/shell.js b/js/src/tests/non262/Promise/shell.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Promise/withResolvers.js b/js/src/tests/non262/Promise/withResolvers.js new file mode 100644 index 0000000000..d689da767b --- /dev/null +++ b/js/src/tests/non262/Promise/withResolvers.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!xulRuntime.shell) -- needs drainJobQueue + +{ + let {resolve, promise} = Promise.withResolvers(); + + let result = undefined; + promise.then((v) => result = v); + resolve(5); + + drainJobQueue(); + assertEq(result, 5); +} + +{ + let {reject, promise} = Promise.withResolvers(); + + let result = undefined; + promise.catch((v) => result = v); + reject("abc"); + + drainJobQueue(); + assertEq(result, "abc"); +} + +reportCompare(true,true); diff --git a/js/src/tests/non262/Proxy/browser.js b/js/src/tests/non262/Proxy/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Proxy/define-writable-as-non-writable.js b/js/src/tests/non262/Proxy/define-writable-as-non-writable.js new file mode 100644 index 0000000000..f764d278f0 --- /dev/null +++ b/js/src/tests/non262/Proxy/define-writable-as-non-writable.js @@ -0,0 +1,19 @@ +"use strict"; + +var target = {}; +Object.defineProperty(target, "test", {configurable: false, writable: true, value: 5}); + +var proxy = new Proxy(target, { + defineProperty(target, property) { + assertEq(property, "test"); + return true; + } +}); + +assertThrowsInstanceOf( + () => Object.defineProperty(proxy, "test", {writable: false}), TypeError); + +assertThrowsInstanceOf( + () => Reflect.defineProperty(proxy, "test", {writable: false}), TypeError); + +reportCompare(0, 0); diff --git a/js/src/tests/non262/Proxy/delete-non-extensible.js b/js/src/tests/non262/Proxy/delete-non-extensible.js new file mode 100644 index 0000000000..b31216bb65 --- /dev/null +++ b/js/src/tests/non262/Proxy/delete-non-extensible.js @@ -0,0 +1,18 @@ +"use strict"; + +var target = { test: true }; +Object.preventExtensions(target); + +var proxy = new Proxy(target, { + deleteProperty(target, property) { + return true; + } +}); + +assertEq(delete proxy.missing, true); +assertEq(Reflect.deleteProperty(proxy, "missing"), true); + +assertThrowsInstanceOf(() => { delete proxy.test; }, TypeError); +assertThrowsInstanceOf(() => Reflect.deleteProperty(proxy, "test"), TypeError); + +reportCompare(0, 0); diff --git a/js/src/tests/non262/Proxy/getPrototypeOf.js b/js/src/tests/non262/Proxy/getPrototypeOf.js new file mode 100644 index 0000000000..a0676c0c91 --- /dev/null +++ b/js/src/tests/non262/Proxy/getPrototypeOf.js @@ -0,0 +1,285 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = "getPrototypeOf.js"; +var BUGNUMBER = 888969; +var summary = "Scripted proxies' [[GetPrototypeOf]] behavior"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +const log = []; + +function observe(obj) +{ + var observingHandler = new Proxy({}, { + get(target, p, receiver) { + log.push(p); + return Reflect.get(target, p, receiver); + } + }); + + return new Proxy(obj, observingHandler); +} + +function nop() {} + +var p, h; + +// 1. Let handler be the value of the [[ProxyHandler]] internal slot of O. +// 2. If handler is null, throw a TypeError exception. +// 3. Assert: Type(handler) is Object. +var rev = Proxy.revocable({}, {}); +p = rev.proxy; + +assertEq(Object.getPrototypeOf(p), Object.prototype); +rev.revoke(); +assertThrowsInstanceOf(() => Object.getPrototypeOf(p), TypeError); + +// 4. Let target be the value of the [[ProxyTarget]] internal slot of O. +// 5. Let trap be ? GetMethod(handler, "getPrototypeOf"). + +// Getting handler.getPrototypeOf might throw. +assertThrowsValue(() => Object.getPrototypeOf(new Proxy({}, + { get getPrototypeOf() { + throw 17; + } })), + 17); + +// The handler's getPrototypeOf, once gotten, might throw. +p = new Proxy({}, { getPrototypeOf() { throw 42; } }); + +assertThrowsValue(() => Object.getPrototypeOf(p), 42); + +// The trap might not be callable. +p = new Proxy({}, { getPrototypeOf: 17 }); + +assertThrowsInstanceOf(() => Object.getPrototypeOf(p), + TypeError); + +// 6. If trap is undefined, then +// a. Return ? target.[[GetPrototypeOf]](). + +var x, tp; + +tp = + new Proxy(new Number(8675309), // behavior overridden by getPrototypeOf + { getPrototypeOf() { x = "getPrototypeOf trap"; return null; } }); + +// The target's [[GetPrototypeOf]] should be invoked if the handler's +// .getPrototypeOf is undefined. +p = new Proxy(tp, { getPrototypeOf: undefined }); +x = "unset"; +assertEq(Object.getPrototypeOf(p), null); +assertEq(x, "getPrototypeOf trap"); + +// Likewise if the handler's .getPrototypeOf is null. +p = new Proxy(tp, { getPrototypeOf: null }); +x = "unset"; +assertEq(Object.getPrototypeOf(p), null); +assertEq(x, "getPrototypeOf trap"); + +// Now the target is an empty object with a Number object as its [[Prototype]]. +var customProto = new Number(8675309); +tp = + new Proxy({}, + { getPrototypeOf() { + x = "getPrototypeOf trap"; + return customProto; + } }); + +// The target's [[GetPrototypeOf]] should be invoked if the handler's +// .getPrototypeOf is undefined. +p = new Proxy(tp, { getPrototypeOf: undefined }); +x = "unset"; +assertEq(Object.getPrototypeOf(p), customProto); +assertEq(x, "getPrototypeOf trap"); + +// Likewise if the handler's .getPrototypeOf is null. +p = new Proxy(tp, { getPrototypeOf: null }); +x = "unset"; +assertEq(Object.getPrototypeOf(p), customProto); +assertEq(x, "getPrototypeOf trap"); + +// 7. Let handlerProto be ? Call(trap, handler, « target »). + +// The trap callable might throw. +p = new Proxy({}, { getPrototypeOf() { throw "ohai"; } }); + +assertThrowsValue(() => Object.getPrototypeOf(p), + "ohai"); + +var throwingTrap = + new Proxy(function() { throw "not called"; }, + { apply() { throw 37; } }); + +p = new Proxy({}, { getPrototypeOf: throwingTrap }); + +assertThrowsValue(() => Object.getPrototypeOf(p), + 37); + +// The trap callable must *only* be called. +p = new Proxy({}, + { + getPrototypeOf: observe(function() { throw "boo-urns"; }) + }); + +log.length = 0; +assertThrowsValue(() => Object.getPrototypeOf(p), + "boo-urns"); + +assertEq(log.length, 1); +assertEq(log[0], "apply"); + +// 8. If Type(handlerProto) is neither Object nor Null, throw a TypeError exception. + +var rval; + +var typeTestingTarget = {}; +p = new Proxy(typeTestingTarget, { getPrototypeOf() { return rval; } }); + +function returnsPrimitives() +{ + rval = undefined; + assertThrowsInstanceOf(() => Object.getPrototypeOf(p), + TypeError); + + rval = true; + assertThrowsInstanceOf(() => Object.getPrototypeOf(p), + TypeError); + + rval = false; + assertThrowsInstanceOf(() => Object.getPrototypeOf(p), + TypeError); + + rval = 0.0; + assertThrowsInstanceOf(() => Object.getPrototypeOf(p), + TypeError); + + rval = -0.0; + assertThrowsInstanceOf(() => Object.getPrototypeOf(p), + TypeError); + + rval = 3.141592654; + assertThrowsInstanceOf(() => Object.getPrototypeOf(p), + TypeError); + + rval = NaN; + assertThrowsInstanceOf(() => Object.getPrototypeOf(p), + TypeError); + + rval = -Infinity; + assertThrowsInstanceOf(() => Object.getPrototypeOf(p), + TypeError); + + rval = "[[Prototype]] FOR REALZ"; + assertThrowsInstanceOf(() => Object.getPrototypeOf(p), + TypeError); + + rval = Symbol("[[Prototype]] FOR REALZ"); + assertThrowsInstanceOf(() => Object.getPrototypeOf(p), + TypeError); +} + +returnsPrimitives(); +Object.preventExtensions(typeTestingTarget); +returnsPrimitives(); + +// 9. Let extensibleTarget be ? IsExtensible(target). + +var act, extens; + +var typeTestingProxyTarget = + new Proxy({}, { isExtensible() { + seen = act(); + return extens; + } }); + +p = new Proxy(typeTestingProxyTarget, { getPrototypeOf() { return rval; } }); + +rval = null; +act = () => { throw "fnord" }; +assertThrowsValue(() => Object.getPrototypeOf(p), + "fnord"); + +rval = /abc/; +act = () => { throw "fnord again" }; +assertThrowsValue(() => Object.getPrototypeOf(p), + "fnord again"); + +rval = Object.prototype; +act = () => { throw "fnord" }; +assertThrowsValue(() => Object.getPrototypeOf(p), + "fnord"); + +// 10. If extensibleTarget is true, return handlerProto. + +p = new Proxy({}, { getPrototypeOf() { return rval; } }); + +rval = Number.prototype; +assertEq(Object.getPrototypeOf(p), Number.prototype); + +// 11. Let targetProto be ? target.[[GetPrototypeOf]](). + +var targetProto; + +var targetWithProto = + new Proxy(Object.preventExtensions(Object.create(null)), + { getPrototypeOf() { act2(); return targetProto; } }); + +p = new Proxy(targetWithProto, + { getPrototypeOf() { act1(); return rval; } }); + +rval = null; +targetProto = null; + +var regex = /targetProto/; + +act1 = () => log.push("act1"); +act2 = () => log.push("act2"); + +log.length = 0; +assertEq(Object.getPrototypeOf(p), null); +assertEq(log.length, 2); +assertEq(log[0], "act1"); +assertEq(log[1], "act2"); + +act1 = () => log.push("act1 again"); +act2 = () => { throw "target throw"; }; + +log.length = 0; +assertThrowsValue(() => Object.getPrototypeOf(p), + "target throw"); +assertEq(log.length, 1); +assertEq(log[0], "act1 again"); + +// 12. If SameValue(handlerProto, targetProto) is false, throw a TypeError exception. + +act1 = act2 = nop; +rval = /a/; +assertThrowsInstanceOf(() => Object.getPrototypeOf(p), + TypeError); + +// 13. Return handlerProto. + +rval = null; +targetProto = null; + +assertEq(Object.getPrototypeOf(p), null); + +p = new Proxy(Object.preventExtensions(new Number(55)), + { getPrototypeOf() { return Number.prototype; } }); + +assertEq(Object.getPrototypeOf(p), Number.prototype); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Proxy/global-receiver.js b/js/src/tests/non262/Proxy/global-receiver.js new file mode 100644 index 0000000000..b2d160c0dd --- /dev/null +++ b/js/src/tests/non262/Proxy/global-receiver.js @@ -0,0 +1,35 @@ +// The global object can be the receiver passed to the get and set traps of a Proxy. +var global = this; +var proto = Object.getPrototypeOf(global); +var gets = 0, sets = 0; + +try { + Object.setPrototypeOf(global, new Proxy(proto, { + has(t, id) { + return id === "bareword" || Reflect.has(t, id); + }, + get(t, id, r) { + gets++; + assertEq(r, global); + return Reflect.get(t, id, r); + }, + set(t, id, v, r) { + sets++; + assertEq(r, global); + return Reflect.set(t, id, v, r); + } + })); +} catch (e) { + global.bareword = undefined; + gets = 1; + sets = 1; +} + +assertEq(bareword, undefined); +assertEq(gets, 1); + +bareword = 12; +assertEq(sets, 1); +assertEq(global.bareword, 12); + +reportCompare(0, 0); diff --git a/js/src/tests/non262/Proxy/hasInstance.js b/js/src/tests/non262/Proxy/hasInstance.js new file mode 100644 index 0000000000..bbdffb2273 --- /dev/null +++ b/js/src/tests/non262/Proxy/hasInstance.js @@ -0,0 +1,13 @@ +var get = []; +var fun = function() {} +var p = new Proxy(fun, { + get(target, key) { + get.push(key); + return target[key]; + } +}); + +assertEq(new fun instanceof p, true); +assertDeepEq(get, [Symbol.hasInstance, "prototype"]); + +reportCompare(true, true); diff --git a/js/src/tests/non262/Proxy/json-stringify-replacer-array-revocable-proxy.js b/js/src/tests/non262/Proxy/json-stringify-replacer-array-revocable-proxy.js new file mode 100644 index 0000000000..5d667e353a --- /dev/null +++ b/js/src/tests/non262/Proxy/json-stringify-replacer-array-revocable-proxy.js @@ -0,0 +1,39 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +var gTestfile = "json-stringify-replacer-array-revocable-proxy.js"; +//----------------------------------------------------------------------------- +var BUGNUMBER = 1196497; +var summary = + "Don't assert when JSON.stringify is passed a revocable proxy to an array, " + + "then that proxy is revoked midflight during stringification"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var arr = []; +var { proxy, revoke } = Proxy.revocable(arr, { + get(thisv, prop, receiver) { + // First (and only) get will be for "length", to determine the length of the + // list of properties to serialize. Returning 0 uses the empty list, + // resulting in |a: 0| being ignored below. + assertEq(thisv, arr); + assertEq(prop, "length"); + assertEq(receiver, proxy); + + revoke(); + return 0; + } +}); + +assertEq(JSON.stringify({a: 0}, proxy), "{}"); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Proxy/ownkeys-allowed-types.js b/js/src/tests/non262/Proxy/ownkeys-allowed-types.js new file mode 100644 index 0000000000..028ab85128 --- /dev/null +++ b/js/src/tests/non262/Proxy/ownkeys-allowed-types.js @@ -0,0 +1,20 @@ +function makeProxy(type) { + return new Proxy({}, { ownKeys() { return [type]; } }); +} + +for (var type of [123, 12.5, true, false, undefined, null, {}, []]) { + var proxy = makeProxy(type); + assertThrowsInstanceOf(() => Object.ownKeys(proxy), TypeError); + assertThrowsInstanceOf(() => Object.getOwnPropertyNames(proxy), TypeError); +} + +type = Symbol(); +proxy = makeProxy(type); +assertEq(Object.getOwnPropertySymbols(proxy)[0], type); + +type = "abc"; +proxy = makeProxy(type); +assertEq(Object.getOwnPropertyNames(proxy)[0], type); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Proxy/ownkeys-linear.js b/js/src/tests/non262/Proxy/ownkeys-linear.js new file mode 100644 index 0000000000..7b05a93846 --- /dev/null +++ b/js/src/tests/non262/Proxy/ownkeys-linear.js @@ -0,0 +1,70 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = 'ownkeys-linear.js'; +var BUGNUMBER = 1257779; +var summary = + "Scripted proxies' [[OwnPropertyKeys]] should have linear complexity"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +// Making this 50k makes cgc builds time out on tbpl. 5k takes 28s locally. +// 10k takes 84s locally. So pick an intermediate number, with a generous +// constant factor in case cgc-on-tbpl is much slower. +const HALF_COUNT = 7500; + +var configurables = []; +for (var i = 0; i < HALF_COUNT; i++) + configurables.push("conf" + i); + +var nonconfigurables = []; +for (var i = 0; i < HALF_COUNT; i++) + nonconfigurables.push("nonconf" + i); + +var target = {}; +for (var name of configurables) + Object.defineProperty(target, name, { configurable: false, value: 0 }); +for (var name of nonconfigurables) + Object.defineProperty(target, name, { configurable: true, value: 0 }); + +var handler = { + ownKeys(t) { + assertEq(t, target, "target mismatch!"); + + var trapResult = []; + + // Append all nonconfigurables in reverse order of presence. + for (var i = nonconfigurables.length; i > 0; i--) + trapResult.push(nonconfigurables[i - 1]); + + // Then the same for all configurables. + for (var i = configurables.length; i > 0; i--) + trapResult.push(configurables[i - 1]); + + // The end consequence is that this ordering is exactly opposite the + // ordering they'll have on the target, and so worst-case performance will + // occur if the spec's |uncheckedResultKeys| structure is a vector having + // the same order as |trapResult|, searched from beginning to end in the + // presence-checks in the last few steps of the [[OwnPropertyKeys]] + // algorithm. + return trapResult; + } +}; + +var p = new Proxy(target, handler); + +// The test passes if it doesn't time out. +assertEq(Object.getOwnPropertyNames(p).length, HALF_COUNT * 2); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Proxy/ownkeys-trap-duplicates.js b/js/src/tests/non262/Proxy/ownkeys-trap-duplicates.js new file mode 100644 index 0000000000..d525662657 --- /dev/null +++ b/js/src/tests/non262/Proxy/ownkeys-trap-duplicates.js @@ -0,0 +1,33 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = 'ownkeys-trap-duplicates.js'; +var BUGNUMBER = 1293995; +var summary = + "Scripted proxies' [[OwnPropertyKeys]] should not throw if the trap " + + "implementation returns duplicate properties and the object is " + + "non-extensible or has non-configurable properties." + + "Revised (bug 1389752): Throw TypeError for duplicate properties."; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var target = Object.preventExtensions({ a: 1 }); +var proxy = new Proxy(target, { ownKeys(t) { return ["a", "a"]; } }); +assertThrowsInstanceOf(() => Object.getOwnPropertyNames(proxy), TypeError); + +target = Object.freeze({ a: 1 }); +proxy = new Proxy(target, { ownKeys(t) { return ["a", "a"]; } }); +assertThrowsInstanceOf(() => Object.getOwnPropertyNames(proxy), TypeError); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Proxy/proxy-__proto__.js b/js/src/tests/non262/Proxy/proxy-__proto__.js new file mode 100644 index 0000000000..f68bea489b --- /dev/null +++ b/js/src/tests/non262/Proxy/proxy-__proto__.js @@ -0,0 +1,59 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = 'proxy-__proto__.js'; +var BUGNUMBER = 950407; +var summary = "Behavior of __proto__ on ES6 proxies"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var protoDesc = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__"); +var protoGetter = protoDesc.get; +var protoSetter = protoDesc.set; + +function testProxy(target, initialProto) +{ + print("Now testing behavior for new Proxy(" + ("" + target) + ", {})"); + + var pobj = new Proxy(target, {}); + + // Check [[Prototype]] before attempted mutation + assertEq(Object.getPrototypeOf(pobj), initialProto); + assertEq(protoGetter.call(pobj), initialProto); + + // Attempt [[Prototype]] mutation + protoSetter.call(pobj, null); + + // Check [[Prototype]] after attempted mutation + assertEq(Object.getPrototypeOf(pobj), null); + assertEq(protoGetter.call(pobj), null); + assertEq(Object.getPrototypeOf(target), null); +} + +// Proxy object with non-null [[Prototype]] +var nonNullProto = { toString: function() { return "non-null prototype"; } }; +var target = Object.create(nonNullProto); +testProxy(target, nonNullProto); + +// Proxy object with null [[Prototype]] +target = Object.create(null); +target.toString = function() { return "null prototype" }; +testProxy(target, null); + +// Proxy function with [[Call]] +var callForCallOnly = function () { }; +callForCallOnly.toString = function() { return "callable target"; }; +testProxy(callForCallOnly, Function.prototype); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Proxy/proxy-constructNonObject.js b/js/src/tests/non262/Proxy/proxy-constructNonObject.js new file mode 100644 index 0000000000..04cee11e96 --- /dev/null +++ b/js/src/tests/non262/Proxy/proxy-constructNonObject.js @@ -0,0 +1,18 @@ +function bogusConstruct(target) { return 4; } +function bogusConstructUndefined(target) { } + +var handler = { construct: bogusConstruct } + +function callable() {} + +var p = new Proxy(callable, handler); + +assertThrowsInstanceOf(function () { new p(); }, TypeError, + "[[Construct must throw if an object is not returned."); + +handler.construct = bogusConstructUndefined; +assertThrowsInstanceOf(function () { new p(); }, TypeError, + "[[Construct must throw if an object is not returned."); + +if (typeof reportCompare === "function") + reportCompare(0,0, "OK"); diff --git a/js/src/tests/non262/Proxy/proxy-for-in.js b/js/src/tests/non262/Proxy/proxy-for-in.js new file mode 100644 index 0000000000..4332bfbbad --- /dev/null +++ b/js/src/tests/non262/Proxy/proxy-for-in.js @@ -0,0 +1,37 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ +"use strict"; + +let steps = []; + +const object = { + __proto__: { + "xyz": 42 + } +}; +const proxy = new Proxy(object, { + ownKeys(target) { + steps.push("ownKeys") + return ["a", "b"]; + }, + + getOwnPropertyDescriptor(target, property) { + steps.push("getOwn-" + property); + return { + value: undefined, + configurable: true, + writable: true, + enumerable: (property === "a") + }; + } +}); + +let iterated = []; +for (let x in proxy) + iterated.push(x); + +assertEq(iterated.toString(), "a,xyz"); +assertEq(steps.toString(), "ownKeys,getOwn-a,getOwn-b"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Proxy/proxy-no-receiver-overwrite.js b/js/src/tests/non262/Proxy/proxy-no-receiver-overwrite.js new file mode 100644 index 0000000000..86d352d454 --- /dev/null +++ b/js/src/tests/non262/Proxy/proxy-no-receiver-overwrite.js @@ -0,0 +1,23 @@ +"use strict"; + +var y = new Proxy({}, { + getOwnPropertyDescriptor(target, key) { + if (key === "a") { + return { configurable: true, get: function(v) {} }; + } else { + assertEq(key, "b"); + return { configurable: true, writable: false, value: 15 }; + } + }, + + defineProperty() { + throw "not invoked"; + } +}) + +// This will invoke [[Set]] on the target, with the proxy as receiver. +assertThrowsInstanceOf(() => y.a = 1, TypeError); +assertThrowsInstanceOf(() => y.b = 2, TypeError); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Proxy/proxy-proto-lazy-props.js b/js/src/tests/non262/Proxy/proxy-proto-lazy-props.js new file mode 100644 index 0000000000..c82c0f935b --- /dev/null +++ b/js/src/tests/non262/Proxy/proxy-proto-lazy-props.js @@ -0,0 +1,61 @@ +function makeProxyPrototype(target) { + return Object.setPrototypeOf(target, new Proxy({}, new Proxy({ + getPrototypeOf() { + return null; + }, + ownKeys() { + return []; + }, + get(t, pk, r) { + throw new Error("Unexpected [[Get]]: " + String(pk)); + } + }, { + get(t, pk, r) { + if (pk in t) + return Reflect.get(t, pk, r); + throw new Error("Unexpected trap called: " + pk); + } + }))); +} + +function enumerateMappedArgs(x) { + var a = makeProxyPrototype(arguments); + + // Delete all lazy properties and ensure no [[Has]] trap is called for them + // on the prototype chain. + delete a.length; + delete a.callee; + delete a[Symbol.iterator]; + delete a[0]; + + for (var k in a); +} +enumerateMappedArgs(0); + +function enumerateUnmappedArgs(x) { + "use strict"; + var a = makeProxyPrototype(arguments); + + delete a.length; + // delete a.callee; // .callee is non-configurable + delete a[Symbol.iterator]; + delete a[0]; + + for (var k in a); +} +enumerateUnmappedArgs(0); + +function enumerateFunction() { + var f = makeProxyPrototype(function named() {}); + + // delete f.prototype; // .prototype is non-configurable + delete f.length; + delete f.name; + + for (var k in f); +} +enumerateFunction(); + + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Proxy/proxy-with-revoked-arguments.js b/js/src/tests/non262/Proxy/proxy-with-revoked-arguments.js new file mode 100644 index 0000000000..a60dddbea6 --- /dev/null +++ b/js/src/tests/non262/Proxy/proxy-with-revoked-arguments.js @@ -0,0 +1,53 @@ +var BUGNUMBER = 1151149; +var summary = "Proxy constructor should not throw if either the target or handler is a revoked proxy."; + +print(BUGNUMBER + ": " + summary); + +var p = new Proxy({}, {}); + +new Proxy(p, {}); +new Proxy({}, p); + +var r = Proxy.revocable({}, {}); +p = r.proxy; + +new Proxy(p, {}); +new Proxy({}, p); + +r.revoke(); + +new Proxy(p, {}); +new Proxy({}, p); + + +var r2 = Proxy.revocable({}, {}); +r = Proxy.revocable(r2.proxy, {}); +p = r.proxy; + +new Proxy(p, {}); +new Proxy({}, p); + +r2.revoke(); + +new Proxy(p, {}); +new Proxy({}, p); + +r.revoke(); + +new Proxy(p, {}); +new Proxy({}, p); + + +var g = newGlobal(); +p = g.eval(`var r = Proxy.revocable({}, {}); r.proxy;`); + +new Proxy(p, {}); +new Proxy({}, p); + +g.eval(`r.revoke();`); + +new Proxy(p, {}); +new Proxy({}, p); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Proxy/regress-bug1037770.js b/js/src/tests/non262/Proxy/regress-bug1037770.js new file mode 100644 index 0000000000..240b04f32e --- /dev/null +++ b/js/src/tests/non262/Proxy/regress-bug1037770.js @@ -0,0 +1,7 @@ +foo = 1; +Object.defineProperty(this, "foo", {writable:false, configurable:true}); +foo = 2; +assertEq(foo, 1); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Proxy/regress-bug1062349.js b/js/src/tests/non262/Proxy/regress-bug1062349.js new file mode 100644 index 0000000000..fe0ad3d9a9 --- /dev/null +++ b/js/src/tests/non262/Proxy/regress-bug1062349.js @@ -0,0 +1,31 @@ +// Adapted from a test case contributed by André Bargull in bug 1062349. + +var log = []; +var hh = { + get(t, pk) { + log.push("trap: " + pk); + return t[pk]; + } +}; +var h = new Proxy({ + get set() { + log.push("called set()"); + Object.defineProperty(o, "prop", {value: 0}); + log.push("o.prop:", Object.getOwnPropertyDescriptor(o, "prop")); + } +}, hh); +var p = new Proxy({}, h); +var o = {__proto__: p}; + +o.prop = 1; + +var expectedDesc = {value: 0, writable: false, enumerable: false, configurable: false}; +assertDeepEq(log, [ + "trap: set", + "called set()", + "o.prop:", + expectedDesc +]); +assertDeepEq(Object.getOwnPropertyDescriptor(o, "prop"), expectedDesc); + +reportCompare(0, 0); diff --git a/js/src/tests/non262/Proxy/regress-bug950407.js b/js/src/tests/non262/Proxy/regress-bug950407.js new file mode 100644 index 0000000000..d253c75fc2 --- /dev/null +++ b/js/src/tests/non262/Proxy/regress-bug950407.js @@ -0,0 +1,7 @@ +var ab = new ArrayBuffer(5); +var p = new Proxy(ab, {}); +var ps = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__").set; +var new_proto = {}; +ps.call(p, new_proto); + +reportCompare(ab.__proto__, new_proto); diff --git a/js/src/tests/non262/Proxy/report-writable-as-non-writable.js b/js/src/tests/non262/Proxy/report-writable-as-non-writable.js new file mode 100644 index 0000000000..c0facd1057 --- /dev/null +++ b/js/src/tests/non262/Proxy/report-writable-as-non-writable.js @@ -0,0 +1,20 @@ +"use strict"; + +var target = {}; +Object.defineProperty(target, "test", + {configurable: false, writable: true, value: 1}); + +var proxy = new Proxy(target, { + getOwnPropertyDescriptor(target, property) { + assertEq(property, "test"); + return {configurable: false, writable: false, value: 1}; + } +}); + +assertThrowsInstanceOf(() => Object.getOwnPropertyDescriptor(proxy, "test"), + TypeError); + +assertThrowsInstanceOf(() => Reflect.getOwnPropertyDescriptor(proxy, "test"), + TypeError); + +reportCompare(0, 0); diff --git a/js/src/tests/non262/Proxy/revocable-proxy-prototype.js b/js/src/tests/non262/Proxy/revocable-proxy-prototype.js new file mode 100644 index 0000000000..7afbc15d2a --- /dev/null +++ b/js/src/tests/non262/Proxy/revocable-proxy-prototype.js @@ -0,0 +1,40 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = 'revocable-proxy-prototype.js'; +var BUGNUMBER = 1052139; +var summary = "Accessing a revocable proxy's [[Prototype]] shouldn't crash"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ +function checkFunctionAppliedToRevokedProxy(fun) +{ + var p = Proxy.revocable({}, {}); + p.revoke(); + + try + { + fun(p.proxy); + throw "didn't throw"; + } + catch (e) + { + assertEq(e instanceof TypeError, true, + "expected TypeError, got " + e); + } +} + +checkFunctionAppliedToRevokedProxy(proxy => Object.getPrototypeOf(proxy)); +checkFunctionAppliedToRevokedProxy(proxy => Object.setPrototypeOf(proxy, null)); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Proxy/revoke-as-side-effect.js b/js/src/tests/non262/Proxy/revoke-as-side-effect.js new file mode 100644 index 0000000000..25d4c9bf91 --- /dev/null +++ b/js/src/tests/non262/Proxy/revoke-as-side-effect.js @@ -0,0 +1,73 @@ +function createProxy(proxyTarget) { + var {proxy, revoke} = Proxy.revocable(proxyTarget, new Proxy({}, { + get(target, propertyKey, receiver) { + print("trap get:", propertyKey); + revoke(); + } + })); + return proxy; +} + +var obj; + +// [[GetPrototypeOf]] +assertEq(Object.getPrototypeOf(createProxy({})), Object.prototype); +assertEq(Object.getPrototypeOf(createProxy([])), Array.prototype); + +// [[SetPrototypeOf]] +obj = {}; +Object.setPrototypeOf(createProxy(obj), Array.prototype); +assertEq(Object.getPrototypeOf(obj), Array.prototype); + +// [[IsExtensible]] +assertEq(Object.isExtensible(createProxy({})), true); +assertEq(Object.isExtensible(createProxy(Object.preventExtensions({}))), false); + +// [[PreventExtensions]] +obj = {}; +Object.preventExtensions(createProxy(obj)); +assertEq(Object.isExtensible(obj), false); + +// [[GetOwnProperty]] +assertEq(Object.getOwnPropertyDescriptor(createProxy({}), "a"), undefined); +assertEq(Object.getOwnPropertyDescriptor(createProxy({a: 5}), "a").value, 5); + +// [[DefineOwnProperty]] +obj = {}; +Object.defineProperty(createProxy(obj), "a", {value: 5}); +assertEq(obj.a, 5); + +// [[HasProperty]] +assertEq("a" in createProxy({}), false); +assertEq("a" in createProxy({a: 5}), true); + +// [[Get]] +assertEq(createProxy({}).a, undefined); +assertEq(createProxy({a: 5}).a, 5); + +// [[Set]] +assertThrowsInstanceOf(() => createProxy({}).a = 0, TypeError); +assertThrowsInstanceOf(() => createProxy({a: 5}).a = 0, TypeError); + +// [[Delete]] +assertEq(delete createProxy({}).a, true); +assertEq(delete createProxy(Object.defineProperty({}, "a", {configurable: false})).a, false); + +// [[OwnPropertyKeys]] +assertEq(Object.getOwnPropertyNames(createProxy({})).length, 0); +assertEq(Object.getOwnPropertyNames(createProxy({a: 5})).length, 1); + +// [[Call]] +assertEq(createProxy(function() { return "ok" })(), "ok"); + +// [[Construct]] +// This throws because after the "construct" trap on the proxy is consulted, +// OrdinaryCreateFromConstructor (called because the |q| function's +// [[ConstructorKind]] is "base" per FunctionAllocate) accesses +// |new.target.prototype| to create the |this| for the construct operation, that +// would be returned if |return obj;| didn't override it. +assertThrowsInstanceOf(() => new (createProxy(function q(){ return obj; })), + TypeError); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Proxy/revoke-no-name.js b/js/src/tests/non262/Proxy/revoke-no-name.js new file mode 100644 index 0000000000..59ea80bd5d --- /dev/null +++ b/js/src/tests/non262/Proxy/revoke-no-name.js @@ -0,0 +1,2 @@ +var revocationFunction = Proxy.revocable({}, {}).revoke; +reportCompare(revocationFunction.name, ""); diff --git a/js/src/tests/non262/Proxy/revoked-get-function-realm-typeerror.js b/js/src/tests/non262/Proxy/revoked-get-function-realm-typeerror.js new file mode 100644 index 0000000000..8214b3c9a7 --- /dev/null +++ b/js/src/tests/non262/Proxy/revoked-get-function-realm-typeerror.js @@ -0,0 +1,119 @@ +var constructors = [ + // 19.1 Object Objects + {constructor: Object}, + + // 19.2 Function Objects + {constructor: Function}, + + // 19.3 Boolean Objects + {constructor: Boolean}, + + // 19.5 Error Objects + {constructor: Error}, + + // 19.5.5 Native Error Types Used in This Standard + {constructor: EvalError}, + {constructor: RangeError}, + {constructor: ReferenceError}, + {constructor: SyntaxError}, + {constructor: TypeError}, + {constructor: URIError}, + + // 20.1 Number Objects + {constructor: Number}, + + // 20.3 Date Objects + {constructor: Date}, + + // 21.1 String Objects + {constructor: String}, + + // 21.2 RegExp (Regular Expression) Objects + {constructor: RegExp}, + + // 22.1 Array Objects + {constructor: Array}, + + // 22.2 TypedArray Objects + {constructor: Int8Array}, + + // 23.1 Map Objects + {constructor: Map}, + + // 23.2 Set Objects + {constructor: Set}, + + // 23.3 WeakMap Objects + {constructor: WeakMap}, + + // 23.4 WeakSet Objects + {constructor: WeakSet}, + + // 24.1 ArrayBuffer Objects + {constructor: ArrayBuffer}, + + // 24.2 SharedArrayBuffer Objects + ...(typeof SharedArrayBuffer === "function" ? [{constructor: SharedArrayBuffer}] : []), + + // 24.3 DataView Objects + {constructor: DataView, args: [new ArrayBuffer(0)]}, + + // 25.2 GeneratorFunction Objects + {constructor: function*(){}.constructor}, + + // 25.3 AsyncGeneratorFunction Objects + {constructor: async function*(){}.constructor}, + + // 25.6 Promise Objects + {constructor: Promise, args: [function(){}]}, + + // 25.7 AsyncFunction Objects + {constructor: async function(){}.constructor}, + + // 9.2 ECMAScript Function Objects + {constructor: function(){}}, + + // Intl can be disabled at compile-time. + ...(typeof Intl !== "undefined" ? [ + // 10 Collator Objects + {constructor: Intl.Collator}, + + // 11 NumberFormat Objects + {constructor: Intl.NumberFormat}, + + // 12 DateTimeFormat Objects + {constructor: Intl.DateTimeFormat}, + + // 13 PluralRules Objects + {constructor: Intl.PluralRules}, + + // Intl.RelativeTimeFormat proposal + {constructor: Intl.RelativeTimeFormat}, + + // Intl.Locale is not yet enabled by default. + ...(Intl.Locale ? [Intl.Locale] : []), + ] : []), +]; + +for (let {constructor, args = []} of constructors) { + let revoked = 0; + let {proxy, revoke} = Proxy.revocable(function(){}, { + get(t, pk, r) { + if (pk === "prototype") { + revoked++; + revoke(); + return undefined; + } + return Reflect.get(t, pk, r); + } + }); + + assertThrowsInstanceOf(() => { + Reflect.construct(constructor, args, proxy); + }, TypeError); + + assertEq(revoked, 1); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Proxy/setPrototypeOf.js b/js/src/tests/non262/Proxy/setPrototypeOf.js new file mode 100644 index 0000000000..d79c53fd96 --- /dev/null +++ b/js/src/tests/non262/Proxy/setPrototypeOf.js @@ -0,0 +1,258 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = "setPrototypeOf.js"; +var BUGNUMBER = 888969; +var summary = "Scripted proxies' [[SetPrototypeOf]] behavior"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +const log = []; + +function observe(obj) +{ + var observingHandler = new Proxy({}, { + get(target, p, receiver) { + log.push(p); + return Reflect.get(target, p, receiver); + } + }); + + return new Proxy(obj, observingHandler); +} + +var p, h; + +// 1. Assert: Either Type(V) is Object or Type(V) is Null. +// 2. Let handler be the value of the [[ProxyHandler]] internal slot of O. +// 3. If handler is null, throw a TypeError exception. +// 4. Assert: Type(handler) is Object. +// 5. Let target be the value of the [[ProxyTarget]] internal slot of O. + +var rev = Proxy.revocable({}, {}); +p = rev.proxy; + +var originalProto = Reflect.getPrototypeOf(p); +assertEq(originalProto, Object.prototype); + +rev.revoke(); +assertThrowsInstanceOf(() => Reflect.setPrototypeOf(p, originalProto), + TypeError); +assertThrowsInstanceOf(() => Reflect.setPrototypeOf(p, null), + TypeError); + +// 6. Let trap be ? GetMethod(handler, "setPrototypeOf"). + +// handler has uncallable (and not null/undefined) property +p = new Proxy({}, { setPrototypeOf: 9 }); +assertThrowsInstanceOf(() => Reflect.setPrototypeOf(p, null), + TypeError); + +p = new Proxy({}, { setPrototypeOf: -3.7 }); +assertThrowsInstanceOf(() => Reflect.setPrototypeOf(p, null), + TypeError); + +p = new Proxy({}, { setPrototypeOf: NaN }); +assertThrowsInstanceOf(() => Reflect.setPrototypeOf(p, null), + TypeError); + +p = new Proxy({}, { setPrototypeOf: Infinity }); +assertThrowsInstanceOf(() => Reflect.setPrototypeOf(p, null), + TypeError); + +p = new Proxy({}, { setPrototypeOf: true }); +assertThrowsInstanceOf(() => Reflect.setPrototypeOf(p, null), + TypeError); + +p = new Proxy({}, { setPrototypeOf: /x/ }); +assertThrowsInstanceOf(() => Reflect.setPrototypeOf(p, null), + TypeError); + +p = new Proxy({}, { setPrototypeOf: Symbol(42) }); +assertThrowsInstanceOf(() => Reflect.setPrototypeOf(p, null), + TypeError); + +p = new Proxy({}, { setPrototypeOf: class X {} }); +assertThrowsInstanceOf(() => Reflect.setPrototypeOf(p, null), + TypeError); + +p = new Proxy({}, observe({})); + +assertEq(Reflect.setPrototypeOf(p, Object.prototype), true); +assertEq(log.length, 1); +assertEq(log[0], "get"); + +h = observe({ setPrototypeOf() { throw 3.14; } }); +p = new Proxy(Object.create(Object.prototype), h); + +// "setting" without change +log.length = 0; +assertThrowsValue(() => Reflect.setPrototypeOf(p, Object.prototype), + 3.14); +assertEq(log.length, 1); +assertEq(log[0], "get"); + +// "setting" with change +log.length = 0; +assertThrowsValue(() => Reflect.setPrototypeOf(p, /foo/), + 3.14); +assertEq(log.length, 1); +assertEq(log[0], "get"); + +// 7. If trap is undefined, then +// a. Return ? target.[[SetPrototypeOf]](V). + +var settingProtoThrows = + new Proxy({}, { setPrototypeOf() { throw "agnizes"; } }); + +p = new Proxy(settingProtoThrows, { setPrototypeOf: undefined }); +assertThrowsValue(() => Reflect.setPrototypeOf(p, null), + "agnizes"); + +p = new Proxy(settingProtoThrows, { setPrototypeOf: null }); +assertThrowsValue(() => Reflect.setPrototypeOf(p, null), + "agnizes"); + +var anotherProto = + new Proxy({}, + { setPrototypeOf(t, p) { + log.push("reached"); + return Reflect.setPrototypeOf(t, p); + } }); + +p = new Proxy(anotherProto, { setPrototypeOf: undefined }); + +log.length = 0; +assertEq(Reflect.setPrototypeOf(p, null), true); +assertEq(log.length, 1); +assertEq(log[0], "reached"); + +p = new Proxy(anotherProto, { setPrototypeOf: null }); + +log.length = 0; +assertEq(Reflect.setPrototypeOf(p, null), true); +assertEq(log.length, 1); +assertEq(log[0], "reached"); + +// 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, « target, V »)). + +// The trap callable might throw. +p = new Proxy({}, { setPrototypeOf() { throw "ohai"; } }); + +assertThrowsValue(() => Reflect.setPrototypeOf(p, /x/), + "ohai"); + +var throwingTrap = + new Proxy(function() { throw "not called"; }, + { apply() { throw 37; } }); + +p = new Proxy({}, { setPrototypeOf: throwingTrap }); + +assertThrowsValue(() => Reflect.setPrototypeOf(p, Object.prototype), + 37); + +// The trap callable must *only* be called. +p = new Proxy({}, + { + setPrototypeOf: observe(function() { throw "boo-urns"; }) + }); + +log.length = 0; +assertThrowsValue(() => Reflect.setPrototypeOf(p, Object.prototype), + "boo-urns"); + +assertEq(log.length, 1); +assertEq(log[0], "apply"); + +// 9. If booleanTrapResult is false, return false. + +p = new Proxy({}, { setPrototypeOf() { return false; } }); +assertEq(Reflect.setPrototypeOf(p, Object.prototype), false); + +p = new Proxy({}, { setPrototypeOf() { return +0; } }); +assertEq(Reflect.setPrototypeOf(p, Object.prototype), false); + +p = new Proxy({}, { setPrototypeOf() { return -0; } }); +assertEq(Reflect.setPrototypeOf(p, Object.prototype), false); + +p = new Proxy({}, { setPrototypeOf() { return NaN; } }); +assertEq(Reflect.setPrototypeOf(p, Object.prototype), false); + +p = new Proxy({}, { setPrototypeOf() { return ""; } }); +assertEq(Reflect.setPrototypeOf(p, Object.prototype), false); + +p = new Proxy({}, { setPrototypeOf() { return undefined; } }); +assertEq(Reflect.setPrototypeOf(p, Object.prototype), false); + +// 10. Let extensibleTarget be ? IsExtensible(target). + +var targetThrowIsExtensible = + new Proxy({}, { isExtensible() { throw "psych!"; } }); + +p = new Proxy(targetThrowIsExtensible, { setPrototypeOf() { return true; } }); +assertThrowsValue(() => Reflect.setPrototypeOf(p, Object.prototype), + "psych!"); + +// 11. If extensibleTarget is true, return true. + +var targ = {}; + +p = new Proxy(targ, { setPrototypeOf() { return true; } }); +assertEq(Reflect.setPrototypeOf(p, /x/), true); +assertEq(Reflect.getPrototypeOf(targ), Object.prototype); +assertEq(Reflect.getPrototypeOf(p), Object.prototype); + +p = new Proxy(targ, { setPrototypeOf() { return /x/; } }); +assertEq(Reflect.setPrototypeOf(p, /x/), true); +assertEq(Reflect.getPrototypeOf(targ), Object.prototype); +assertEq(Reflect.getPrototypeOf(p), Object.prototype); + +p = new Proxy(targ, { setPrototypeOf() { return Infinity; } }); +assertEq(Reflect.setPrototypeOf(p, /x/), true); +assertEq(Reflect.getPrototypeOf(targ), Object.prototype); +assertEq(Reflect.getPrototypeOf(p), Object.prototype); + +p = new Proxy(targ, { setPrototypeOf() { return Symbol(true); } }); +assertEq(Reflect.setPrototypeOf(p, /x/), true); +assertEq(Reflect.getPrototypeOf(targ), Object.prototype); +assertEq(Reflect.getPrototypeOf(p), Object.prototype); + +// 12. Let targetProto be ? target.[[GetPrototypeOf]](). + +var targetNotExtensibleGetProtoThrows = + new Proxy(Object.preventExtensions({}), + { getPrototypeOf() { throw NaN; } }); + +p = new Proxy(targetNotExtensibleGetProtoThrows, + { setPrototypeOf() { log.push("goober"); return true; } }); + +log.length = 0; +assertThrowsValue(() => Reflect.setPrototypeOf(p, /abcd/), + NaN); + +// 13. If SameValue(V, targetProto) is false, throw a TypeError exception. + +var newProto; + +p = new Proxy(Object.preventExtensions(Object.create(Math)), + { setPrototypeOf(t, p) { return true; } }); + +assertThrowsInstanceOf(() => Reflect.setPrototypeOf(p, null), + TypeError); + +// 14. Return true. + +assertEq(Reflect.setPrototypeOf(p, Math), true); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Proxy/shell.js b/js/src/tests/non262/Proxy/shell.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Proxy/trap-null.js b/js/src/tests/non262/Proxy/trap-null.js new file mode 100644 index 0000000000..703649e7c8 --- /dev/null +++ b/js/src/tests/non262/Proxy/trap-null.js @@ -0,0 +1,103 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = 'trap-null.js'; +var BUGNUMBER = 1257102; +var summary = "null as a trap value on a handler should operate on the target"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +// This might seem like overkill, but this proxying trick caught typos of +// several trap names before this test landed. \o/ /o\ +var allTraps = { + getPrototypeOf: null, + setPrototypeOf: null, + isExtensible: null, + preventExtensions: null, + getOwnPropertyDescriptor: null, + defineProperty: null, + has: null, + get: null, + set: null, + deleteProperty: null, + ownKeys: null, + apply: null, + construct: null, +}; + +var complainingHandler = new Proxy(allTraps, { + get(target, p, receiver) { + var v = Reflect.get(target, p, receiver); + if (v !== null) + throw new TypeError("failed to set one of the traps to null? " + p); + + return v; + } +}); + +var proxyTarget = function(x) { + "use strict"; + var str = this + x; + str += new.target ? "constructing" : "calling"; + return new.target ? new String(str) : str; +}; +proxyTarget.prototype.toString = () => "###"; +proxyTarget.prototype.valueOf = () => "@@@"; + +var proxy = new Proxy(proxyTarget, complainingHandler); + +assertEq(Reflect.getPrototypeOf(proxy), Function.prototype); + +assertEq(Object.getPrototypeOf(proxyTarget), Function.prototype); +assertEq(Reflect.setPrototypeOf(proxy, null), true); +assertEq(Object.getPrototypeOf(proxyTarget), null); + +assertEq(Reflect.isExtensible(proxy), true); + +assertEq(Reflect.isExtensible(proxyTarget), true); +assertEq(Reflect.preventExtensions(proxy), true); +assertEq(Reflect.isExtensible(proxy), false); +assertEq(Reflect.isExtensible(proxyTarget), false); + +var desc = Reflect.getOwnPropertyDescriptor(proxy, "length"); +assertEq(desc.value, 1); + +assertEq(desc.configurable, true); +assertEq(Reflect.defineProperty(proxy, "length", { value: 3, configurable: false }), true); +desc = Reflect.getOwnPropertyDescriptor(proxy, "length"); +assertEq(desc.configurable, false); + +assertEq(Reflect.has(proxy, "length"), true); + +assertEq(Reflect.get(proxy, "length"), 3); + +assertEq(Reflect.set(proxy, "length", 3), false); + +assertEq(Reflect.deleteProperty(proxy, "length"), false); + +var keys = Reflect.ownKeys(proxy); +assertEq(keys.length, 3); +keys.sort(); +assertEq(keys[0], "length"); +assertEq(keys[1], "name"); +assertEq(keys[2], "prototype"); + +assertEq(Reflect.apply(proxy, "hi!", [" "]), "hi! calling"); + +var res = Reflect.construct(proxy, [" - "]); +assertEq(typeof res, "object"); +assertEq(res instanceof String, true); +assertEq(res.valueOf(), "@@@ - constructing"); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/ReadableStream/basic-pull.js b/js/src/tests/non262/ReadableStream/basic-pull.js new file mode 100644 index 0000000000..760937c67a --- /dev/null +++ b/js/src/tests/non262/ReadableStream/basic-pull.js @@ -0,0 +1,37 @@ +// |reftest| skip-if(!this.ReadableStream||!this.drainJobQueue) + +if ("ignoreUnhandledRejections" in this) { + ignoreUnhandledRejections(); +} + +// Example of a stream that produces data on demand, the "pull" model. +let fibStream = new ReadableStream({ + start(controller) { + this.a = 0; + this.b = 1; + controller.enqueue(0); + controller.enqueue(1); + }, + + pull(controller) { + [this.a, this.b] = [this.b, this.a + this.b]; + controller.enqueue(this.b); + } +}); + +async function test() { + assertEq(fibStream.locked, false); + let reader = fibStream.getReader(); + assertEq(fibStream.locked, true); + + let results = []; + while (results.length < 10) { + results.push((await reader.read()).value); + } + + assertEq(results.join(), "0,1,1,2,3,5,8,13,21,34"); + reader.releaseLock(); + assertEq(fibStream.locked, false); +} + +runAsyncTest(test); diff --git a/js/src/tests/non262/ReadableStream/basic-push.js b/js/src/tests/non262/ReadableStream/basic-push.js new file mode 100644 index 0000000000..65bb29880d --- /dev/null +++ b/js/src/tests/non262/ReadableStream/basic-push.js @@ -0,0 +1,53 @@ +// |reftest| skip-if(!this.ReadableStream||!this.drainJobQueue) + +if ("ignoreUnhandledRejections" in this) { + ignoreUnhandledRejections(); +} + +// Example of a stream that enqueues data asynchronously, whether the reader +// wants it or not, the "push" model. +let fbStream = new ReadableStream({ + start(controller) { + simulatePacketsDriftingIn(controller); + }, +}); + +async function simulatePacketsDriftingIn(controller) { + for (let i = 1; i <= 30; i++) { + let importantData = + (i % 15 == 0 ? "FizzBuzz" : + i % 5 == 0 ? "Buzz": + i % 3 == 0 ? "Fizz" : + String(i)); + controller.enqueue(importantData); + await asyncSleep(1 + i % 7); + } + controller.close(); +} + +const expected = [ + "1", "2", "Fizz", "4", "Buzz", "Fizz", "7", "8", "Fizz", "Buzz", + "11", "Fizz", "13", "14", "FizzBuzz", "16", "17", "Fizz", "19", "Buzz", + "Fizz", "22", "23", "Fizz", "Buzz", "26", "Fizz", "28", "29", "FizzBuzz" +]; + +async function test() { + assertEq(fbStream.locked, false); + let reader = fbStream.getReader(); + assertEq(fbStream.locked, true); + + let results = []; + while (true) { + let r = await reader.read(); + if (r.done) { + break; + } + results.push(r.value); + } + + assertEq(results.join("-"), expected.join("-")); + reader.releaseLock(); + assertEq(fbStream.locked, false); +} + +runAsyncTest(test); diff --git a/js/src/tests/non262/ReadableStream/bug-1501502.js b/js/src/tests/non262/ReadableStream/bug-1501502.js new file mode 100644 index 0000000000..e6b5c0c85b --- /dev/null +++ b/js/src/tests/non262/ReadableStream/bug-1501502.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('ReadableStream')) +// A stream can become errored with an exception from another realm. + +let g = newGlobal(); +let g_enqueue; +new g.ReadableStream({ + start(controller) { + g_enqueue = controller.enqueue; + }, +}); + +let controller; +let stream = new ReadableStream({ + start(c) { + controller = c; + } +}, { + size(chunk) {} +}); + +assertThrowsInstanceOf(() => g_enqueue.call(controller, {}), g.RangeError); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); + diff --git a/js/src/tests/non262/ReadableStream/bug-1549768.js b/js/src/tests/non262/ReadableStream/bug-1549768.js new file mode 100644 index 0000000000..747cb895a9 --- /dev/null +++ b/js/src/tests/non262/ReadableStream/bug-1549768.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('ReadableStream')) + +var otherGlobal = newGlobal({ newCompartment: true }); +var obj = { start(c) { } }; +var Cancel = otherGlobal.ReadableStream.prototype.tee.call(new ReadableStream(obj))[0].cancel; + +var stream = new ReadableStream(obj); +var [branch1, branch2] = ReadableStream.prototype.tee.call(stream); + +Cancel.call(branch1, {}); + +gczeal(2, 1); + +Cancel.call(branch2, {}); + +if (typeof reportCompare === 'function') { + reportCompare(0, 0); +} diff --git a/js/src/tests/non262/ReadableStream/closed-is-handled.js b/js/src/tests/non262/ReadableStream/closed-is-handled.js new file mode 100644 index 0000000000..276cfbbaff --- /dev/null +++ b/js/src/tests/non262/ReadableStream/closed-is-handled.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.ReadableStream||!this.drainJobQueue) + +// 3.5.6. ReadableStreamError ( stream, e ) nothrow +// +// 9. Reject reader.[[closedPromise]] with e. +// 10. Set reader.[[closedPromise]].[[PromiseIsHandled]] to true. +// +// Rejection for [[closedPromise]] shouldn't be reported as unhandled. + +const rs = new ReadableStream({ + start() { + return Promise.reject(new Error("test")); + } +}); + +let rejected = false; +rs.getReader().read().then(() => {}, () => { rejected = true; }); + +drainJobQueue(); + +assertEq(rejected, true); + +if (typeof reportCompare === 'function') { + reportCompare(0, 0); +} + +// Shell itself reports unhandled rejection if there's any. diff --git a/js/src/tests/non262/ReadableStream/constructor-default.js b/js/src/tests/non262/ReadableStream/constructor-default.js new file mode 100644 index 0000000000..9f60204c72 --- /dev/null +++ b/js/src/tests/non262/ReadableStream/constructor-default.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('ReadableStream')) + +// The second argument to `new ReadableStream` defaults to `{}`, so it observes +// properties hacked onto Object.prototype. + +let log = []; + +Object.defineProperty(Object.prototype, "size", { + configurable: true, + get() { + log.push("size"); + log.push(this); + return undefined; + } +}); +Object.prototype.highWaterMark = 1337; + +let s = new ReadableStream({ + start(controller) { + log.push("start"); + log.push(controller.desiredSize); + } +}); +assertDeepEq(log, ["size", {}, "start", 1337]); + +if (typeof reportCompare == "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/ReadableStream/readable-stream-globals.js b/js/src/tests/non262/ReadableStream/readable-stream-globals.js new file mode 100644 index 0000000000..37e73d5cbf --- /dev/null +++ b/js/src/tests/non262/ReadableStream/readable-stream-globals.js @@ -0,0 +1,367 @@ +// |reftest| skip-if(!this.hasOwnProperty("ReadableStream")) + +if ("ignoreUnhandledRejections" in this) { + ignoreUnhandledRejections(); +} + +async function test() { + if (typeof newGlobal !== 'undefined') { + otherGlobal = newGlobal(); + } + + OtherReadableStream = otherGlobal.ReadableStream; + + ReadableStreamReader = new ReadableStream().getReader().constructor; + OtherReadableStreamReader = new otherGlobal.ReadableStream().getReader().constructor; + + let byteStreamsSupported = false; + try { + let controller; + let reader = new ReadableStream({ + start(c) { + ByteStreamController = c.constructor; + controller = c; + }, + type: "bytes" + }).getReader({ mode: "byob" }) + ReadableStreamBYOBReader = reader.constructor; + reader.read(new Uint8Array(10)); + BYOBRequest = controller.byobRequest.constructor; + reader = new otherGlobal.ReadableStream({ + start(c) { + OtherByteStreamController = c.constructor; + controller = c; + }, + type: "bytes" + }).getReader({ mode: "byob" }); + OtherReadableStreamBYOBReader = reader.constructor; + reader.read(new Uint8Array(10)); + OtherBYOBRequest = controller.byobRequest.constructor; + + BYOBRequestGetter = Object.getOwnPropertyDescriptor(ByteStreamController.prototype, + "byobRequest").get; + OtherBYOBRequestGetter = Object.getOwnPropertyDescriptor(OtherByteStreamController.prototype, + "byobRequest").get; + + byteStreamsSupported = true; + } catch (e) { + } + + let chunk = { name: "chunk" }; + let enqueuedError = { name: "enqueuedError" }; + + let controller; + let stream; + let otherStream; + let otherController; + let reader; + let otherReader; + + function getFreshInstances(type, otherType = type) { + stream = new ReadableStream({ start(c) { controller = c; }, type }); + + otherStream = new OtherReadableStream({ start(c) { otherController = c; }, type: otherType }); + } + + getFreshInstances(); + + Controller = controller.constructor; + OtherController = otherController.constructor; + + + otherReader = OtherReadableStream.prototype.getReader.call(stream); + assertEq(otherReader instanceof ReadableStreamReader, false); + assertEq(otherReader instanceof OtherReadableStreamReader, true); + assertEq(otherController instanceof Controller, false); + + assertEq(stream.locked, true); + Object.defineProperty(stream, "locked", + Object.getOwnPropertyDescriptor(OtherReadableStream.prototype, "locked")); + assertEq(stream.locked, true); + + + request = otherReader.read(); + assertEq(request instanceof otherGlobal.Promise, true); + controller.close(); + assertEq(await request instanceof Object, true); + + getFreshInstances(); + otherReader = new OtherReadableStreamReader(stream); + + getFreshInstances(); + otherReader = new OtherReadableStreamReader(stream); + let cancelSucceeded = false; + let cancelPromise = ReadableStreamReader.prototype.cancel.call(otherReader); + assertEq(cancelPromise instanceof Promise, true); + assertEq(await cancelPromise, undefined); + + getFreshInstances(); + otherReader = new OtherReadableStreamReader(stream); + let closeSucceeded = false; + Object.defineProperty(otherReader, "closed", + Object.getOwnPropertyDescriptor(ReadableStreamReader.prototype, "closed")); + let closedPromise = otherReader.closed; + assertEq(closedPromise instanceof otherGlobal.Promise, true); + controller.close(); + assertEq(await closedPromise, undefined); + + getFreshInstances(); + + otherReader = OtherReadableStream.prototype.getReader.call(stream); + request = otherReader.read(); + assertEq(request instanceof otherGlobal.Promise, true); + otherController.close.call(controller); + assertEq(await request instanceof otherGlobal.Object, true); + + getFreshInstances(); + + assertEq(controller.desiredSize, 1); + Object.defineProperty(controller, "desiredSize", + Object.getOwnPropertyDescriptor(OtherController.prototype, "desiredSize")); + assertEq(controller.desiredSize, 1); + + + request = otherReader.read(); + + controller.error(enqueuedError); + + expectException(() => controller.close(), TypeError); + expectException(() => otherController.close.call(controller), otherGlobal.TypeError); + + otherReader.releaseLock(); + + reader = stream.getReader(); + assertEq(await expectAsyncException(async () => reader.read(), enqueuedError.constructor), + enqueuedError); + + otherReader.releaseLock.call(reader); + assertEq(reader.closed instanceof otherGlobal.Promise, true); + + // getFreshInstances(); + + // reader = stream.getReader(); + // request = otherReader.read.call(reader); + // assertEq(request instanceof otherGlobal.Promise, true); + // controller.enqueue(chunk); + // assertEq((await request).value, chunk); + + // reader.releaseLock(); + + // getFreshInstances(); + + // reader = stream.getReader(); + // request = otherReader.read.call(reader); + // otherController.enqueue.call(controller, chunk); + // otherController.enqueue.call(controller, new otherGlobal.Uint8Array(10)); + // controller.enqueue(new otherGlobal.Uint8Array(10)); + // request = otherReader.read.call(reader); + + getFreshInstances(); + + stream = new ReadableStream({ start(c) { controller = c; } }, { size() {return 1} }); + otherController.enqueue.call(controller, chunk); + otherController.enqueue.call(controller, new otherGlobal.Uint8Array(10)); + controller.enqueue(new otherGlobal.Uint8Array(10)); + + getFreshInstances(); + + controller.close(); + expectException(() => controller.enqueue(new otherGlobal.Uint8Array(10)), TypeError); + expectException(() => otherController.enqueue.call(controller, chunk), otherGlobal.TypeError); + expectException(() => otherController.enqueue.call(controller, new otherGlobal.Uint8Array(10)), + otherGlobal.TypeError); + + getFreshInstances(); + + let [branch1, branch2] = otherGlobal.ReadableStream.prototype.tee.call(stream); + assertEq(branch1 instanceof otherGlobal.ReadableStream, true); + assertEq(branch2 instanceof otherGlobal.ReadableStream, true); + + controller.enqueue(chunk); + reader = branch1.getReader(); + result = await reader.read(); + reader.releaseLock(); + let subPromiseCreated = false; + let speciesInvoked = false; + class SubPromise extends Promise { + constructor(executor) { + super(executor); + subPromiseCreated = true; + } + } + Object.defineProperty(Promise, Symbol.species, {get: function() { + speciesInvoked = true; + return SubPromise; + } + }); + + otherGlobal.eval(` + subPromiseCreated = false; + speciesInvoked = false; + class OtherSubPromise extends Promise { + constructor(executor) { + super(executor); + subPromiseCreated = true; + } + } + Object.defineProperty(Promise, Symbol.species, {get: function() { + speciesInvoked = true; + return OtherSubPromise; + } + });`); + + controller.error(enqueuedError); + subPromiseCreated = false; + speciesInvoked = false; + otherGlobal.subPromiseCreated = false; + otherGlobal.speciesInvoked = false; + let cancelPromise1 = branch1.cancel({ name: "cancel 1" }); + assertEq(cancelPromise1 instanceof otherGlobal.Promise, true); + assertEq(subPromiseCreated, false); + assertEq(speciesInvoked, false); + assertEq(otherGlobal.subPromiseCreated, false); + assertEq(otherGlobal.speciesInvoked, false); + subPromiseCreated = false; + speciesInvoked = false; + otherGlobal.subPromiseCreated = false; + otherGlobal.speciesInvoked = false; + let cancelPromise2 = branch2.cancel({ name: "cancel 2" }); + assertEq(cancelPromise2 instanceof otherGlobal.Promise, true); + assertEq(subPromiseCreated, false); + assertEq(speciesInvoked, false); + assertEq(otherGlobal.subPromiseCreated, false); + assertEq(otherGlobal.speciesInvoked, false); + await 1; + + + getFreshInstances(); + + [branch1, branch2] = otherGlobal.ReadableStream.prototype.tee.call(stream); + assertEq(branch1 instanceof otherGlobal.ReadableStream, true); + assertEq(branch2 instanceof otherGlobal.ReadableStream, true); + + controller.enqueue(chunk); + reader = branch1.getReader(); + result = await reader.read(); + reader.releaseLock(); + + + assertEq(result.value, chunk); + + controller.error(enqueuedError); + subPromiseCreated = false; + speciesInvoked = false; + otherGlobal.subPromiseCreated = false; + otherGlobal.speciesInvoked = false; + cancelPromise1 = ReadableStream.prototype.cancel.call(branch1, { name: "cancel 1" }); + assertEq(cancelPromise1 instanceof Promise, true); + assertEq(subPromiseCreated, false); + assertEq(speciesInvoked, false); + assertEq(otherGlobal.subPromiseCreated, false); + assertEq(otherGlobal.speciesInvoked, false); + subPromiseCreated = false; + speciesInvoked = false; + otherGlobal.subPromiseCreated = false; + otherGlobal.speciesInvoked = false; + cancelPromise2 = ReadableStream.prototype.cancel.call(branch2, { name: "cancel 2" }); + assertEq(cancelPromise2 instanceof Promise, true); + assertEq(subPromiseCreated, false); + assertEq(speciesInvoked, false); + assertEq(otherGlobal.subPromiseCreated, false); + assertEq(otherGlobal.speciesInvoked, false); + + if (!byteStreamsSupported) { + return; + } + + if (typeof nukeCCW === 'function') { + getFreshInstances("bytes"); + assertEq(otherController instanceof OtherByteStreamController, true); + reader = ReadableStream.prototype.getReader.call(otherStream); + otherGlobal.reader = reader; + otherGlobal.nukeCCW(otherGlobal.reader); + let chunk = new Uint8Array(10); + expectException(() => otherController.enqueue(chunk), otherGlobal.TypeError); + // otherController.error(); + expectException(() => reader.read(), TypeError); + } + + function testBYOBRequest(controller, view) { + const request = new BYOBRequest(controller, view); + let storedView = request.view; + assertEq(storedView, view); + storedView = Object.getOwnPropertyDescriptor(OtherBYOBRequest.prototype, "view").get.call(request); + assertEq(storedView, view); + request.respond(10); + OtherBYOBRequest.prototype.respond.call(request, 10); + request.respondWithNewView(new view.constructor(10)); + OtherBYOBRequest.prototype.respondWithNewView.call(request, new view.constructor(10)); + } + + expectException(() => new BYOBRequest(), TypeError); + getFreshInstances("bytes"); + expectException(() => new BYOBRequest(controller, new Uint8Array(10)), TypeError); + expectException(() => new BYOBRequest(otherController, new Uint8Array(10)), TypeError); + expectException(() => new BYOBRequest(otherController, new Uint8Array(10)), TypeError); + expectException(() => new BYOBRequest(otherController, new otherGlobal.Uint8Array(10)), TypeError); + + getFreshInstances("bytes"); + + reader = stream.getReader({ mode: "byob" }); + request = OtherReadableStreamBYOBReader.prototype.read.call(reader, new Uint8Array(10)); + assertEq(request instanceof otherGlobal.Promise, true); + controller.enqueue(new Uint8Array([1, 2, 3, 4])); + result = await request; + + getFreshInstances("bytes"); + + reader = stream.getReader({ mode: "byob" }); + request = OtherReadableStreamBYOBReader.prototype.read.call(reader, new Uint8Array(10)); + assertEq(request instanceof otherGlobal.Promise, true); + try { + let byobRequest = OtherBYOBRequestGetter.call(controller); + } catch (e) { + print(e, '\n', e.stack); + } + controller.enqueue(new Uint8Array([1, 2, 3, 4])); + result = await request; + + await 1; +} + +function expectException(closure, errorType) { + let error; + try { + closure(); + } catch (e) { + error = e; + } + assertEq(error !== undefined, true); + assertEq(error.constructor, errorType); + return error; +} + +async function expectAsyncException(closure, errorType) { + let error; + try { + await closure(); + } catch (e) { + error = e; + } + assertEq(error !== undefined, true); + assertEq(error.constructor, errorType); + return error; +} + +async function runTest() { + try { + await test(); + } catch (e) { + assertEq(false, true, `Unexpected exception ${e}\n${e.stack}`); + } + console.log("done"); + if (typeof reportCompare === "function") + reportCompare(true, true); +} + +runTest(); diff --git a/js/src/tests/non262/ReadableStream/shell.js b/js/src/tests/non262/ReadableStream/shell.js new file mode 100644 index 0000000000..7e83ed2934 --- /dev/null +++ b/js/src/tests/non262/ReadableStream/shell.js @@ -0,0 +1,30 @@ +// Return a promise that will resolve to `undefined` the next time jobs are +// processed. +// +// `ticks` indicates how long the promise should "wait" before resolving: a +// promise created with `asyncSleep(n)` will become settled and fire its handlers +// before a promise created with `asyncSleep(n+1)`. +// +function asyncSleep(ticks) { + let p = Promise.resolve(); + if (ticks > 0) { + return p.then(() => asyncSleep(ticks - 1)); + } + return p; +} + +// Run the async function `test`. Wait for it to finish running. Throw if it +// throws or if it fails to finish (awaiting a value forever). +function runAsyncTest(test) { + let passed = false; + let problem = "test did not finish"; + test() + .then(_ => { passed = true; }) + .catch(exc => { problem = exc; }); + drainJobQueue(); + if (!passed) { + throw problem; + } + + reportCompare(0, 0); +} diff --git a/js/src/tests/non262/ReadableStream/subclassing.js b/js/src/tests/non262/ReadableStream/subclassing.js new file mode 100644 index 0000000000..813ed278c2 --- /dev/null +++ b/js/src/tests/non262/ReadableStream/subclassing.js @@ -0,0 +1,111 @@ +// |reftest| skip-if(!xulRuntime.shell||!this.hasOwnProperty('ReadableStream')) -- needs drainJobQueue + +if ("ignoreUnhandledRejections" in this) { + ignoreUnhandledRejections(); +} + +// Spot-check subclassing of stream constructors. + +// ReadableStream can be subclassed. +class PartyStreamer extends ReadableStream {} + +// The base class constructor is called. +let started = false; +let stream = new PartyStreamer({ + // (The ReadableStream constructor calls this start method.) + start(c) { started = true; } +}); +drainJobQueue(); +assertEq(started, true); + +// The instance's prototype chain is correct. +assertEq(stream.__proto__, PartyStreamer.prototype); +assertEq(stream.__proto__.__proto__, ReadableStream.prototype); +assertEq(stream.__proto__.__proto__.__proto__, Object.prototype); +assertEq(stream.__proto__.__proto__.__proto__.__proto__, null); +assertEq(stream instanceof ReadableStream, true); + +// Non-generic methods can be called on the resulting stream. +let reader = stream.getReader(); +assertEq(stream.locked, true); + + +// CountQueuingStrategy can be subclassed. +class PixelStrategy extends CountQueuingStrategy {} +assertEq(new PixelStrategy({highWaterMark: 4}).__proto__, PixelStrategy.prototype); + +// The base class constructor is called. +assertThrowsInstanceOf(() => new PixelStrategy, TypeError); +assertEq(new PixelStrategy({highWaterMark: -1}).highWaterMark, -1); + + +// VerySmartStrategy can be subclassed. +class VerySmartStrategy extends ByteLengthQueuingStrategy { + size(chunk) { + return super.size(chunk) * 8; + } +} +let vss = new VerySmartStrategy({highWaterMark: 12}); +assertEq(vss.size(new ArrayBuffer(8)), 64); +assertEq(vss.__proto__, VerySmartStrategy.prototype); + + +// Even ReadableStreamDefaultReader can be subclassed. +async function readerTest() { + const ReadableStreamDefaultReader = new ReadableStream().getReader().constructor; + class MindReader extends ReadableStreamDefaultReader { + async read() { + let foretold = {value: "death", done: false}; + let actual = await super.read(); + actual = foretold; // ZOMG I WAS RIGHT, EXACTLY AS FORETOLD they should call me a righter + return actual; + } + } + + let stream = new ReadableStream({ + start(c) { c.enqueue("one"); c.enqueue("two"); }, + pull(c) { c.close(); } + }); + let reader = new MindReader(stream); + let result = await reader.read(); + assertEq(result.value, "death"); + reader.releaseLock(); + + reader = stream.getReader(); + result = await reader.read(); + assertEq(result.done, false); + assertEq(result.value, "two"); + result = await reader.read(); + assertEq(result.done, true); + assertEq(result.value, undefined); +} +runAsyncTest(readerTest); + + +// Even ReadableStreamDefaultController, which can't be constructed, +// can be subclassed. +let ReadableStreamDefaultController; +new ReadableStream({ + start(c) { + ReadableStreamDefaultController = c.constructor; + } +}); +class MasterController extends ReadableStreamDefaultController { + constructor() { + // don't call super, it'll just throw + return Object.create(MasterController.prototype); + } +} +let c = new MasterController(); + +// The prototype chain is per spec. +assertEq(c instanceof ReadableStreamDefaultController, true); + +// But the instance does not have the internal slots of a +// ReadableStreamDefaultController, so the non-generic methods can't be used. +assertThrowsInstanceOf(() => c.enqueue("horse"), TypeError); + + +if (typeof reportCompare === 'function') { + reportCompare(0, 0); +} diff --git a/js/src/tests/non262/ReadableStream/tee-start.js b/js/src/tests/non262/ReadableStream/tee-start.js new file mode 100644 index 0000000000..dbb6b1142d --- /dev/null +++ b/js/src/tests/non262/ReadableStream/tee-start.js @@ -0,0 +1,11 @@ +// |reftest| skip-if(!this.ReadableStream||!this.drainJobQueue) +// stream.tee() shouldn't try to call a .start() method. + +Object.prototype.start = function () { throw "FAIL"; }; +let source = Object.create(null); +new ReadableStream(source).tee(); + +drainJobQueue(); + +if (typeof reportCompare == 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/Record/browser.js b/js/src/tests/non262/Record/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Record/constructor.js b/js/src/tests/non262/Record/constructor.js new file mode 100644 index 0000000000..827179c68e --- /dev/null +++ b/js/src/tests/non262/Record/constructor.js @@ -0,0 +1,37 @@ +// |reftest| skip-if(!this.hasOwnProperty("Record")) + +assertThrowsInstanceOf( + () => new Record(), + TypeError, + "Record is not a constructor" +); + +assertEq(typeof Record({}), "record"); +assertEq(typeof Object(Record({})), "object"); +assertEq(Record({}) instanceof Record, false); + +// TODO: It's still not decided what the prototype of records should be +//assertThrowsInstanceOf(() => Object(Record({})) instanceof Record, TypeError); +// assertEq(Record.prototype, null); +// assertEq(Record({}).__proto__, null); +// assertEq(Object(Record({})).__proto__, null); + +assertThrowsInstanceOf( + () => Record(), + TypeError, + "can't convert undefined to object" +); + +assertThrowsInstanceOf( + () => Record(undefined), + TypeError, + "can't convert undefined to object" +); + +assertThrowsInstanceOf( + () => Record(null), + TypeError, + "can't convert null to object" +); + +if (typeof reportCompare === "function") reportCompare(0, 0); diff --git a/js/src/tests/non262/Record/cross-realm.js b/js/src/tests/non262/Record/cross-realm.js new file mode 100644 index 0000000000..e67a07d51e --- /dev/null +++ b/js/src/tests/non262/Record/cross-realm.js @@ -0,0 +1,9 @@ +// |reftest| skip-if(!this.hasOwnProperty("Record")) + +const realm = newGlobal(); + +const realm_record = realm.eval(`Record({ x: 1, y: 2 })`); + +assertEq(realm_record === #{ x: 1, y: 2 }, true); + +if (typeof reportCompare === "function") reportCompare(0, 0); diff --git a/js/src/tests/non262/Record/enumeration.js b/js/src/tests/non262/Record/enumeration.js new file mode 100644 index 0000000000..9ed7bec415 --- /dev/null +++ b/js/src/tests/non262/Record/enumeration.js @@ -0,0 +1,54 @@ +// |reftest| skip-if(!this.hasOwnProperty("Record")) + +var rec = #{ x: 1, y: 2, a: 3 }; + +var keys = Object.keys(rec); +assertEq(keys.length, 3); +assertEq(keys[0], "a"); +assertEq(keys[1], "x"); +assertEq(keys[2], "y"); + +var values = Object.values(rec); +assertEq(values.length, 3); +assertEq(values[0], 3); +assertEq(values[1], 1); +assertEq(values[2], 2); + +var entries = Object.entries(rec); +assertEq(entries.length, 3); +assertEq(entries[0][0], "a"); +assertEq(entries[0][1], 3); +assertEq(entries[1][0], "x"); +assertEq(entries[1][1], 1); +assertEq(entries[2][0], "y"); +assertEq(entries[2][1], 2); + +var ownKeys = Reflect.ownKeys(Object(rec)); +assertEq(ownKeys.length, 3); +assertEq(ownKeys[0], "a"); +assertEq(ownKeys[1], "x"); +assertEq(ownKeys[2], "y"); + +var spreadKeys = Object.keys({ ...rec }); +assertEq(spreadKeys.length, 3); +assertEq(spreadKeys[0], "a"); +assertEq(spreadKeys[1], "x"); +assertEq(spreadKeys[2], "y"); + +var spreadKeysObj = Object.keys({ ...Object(rec) }); +assertEq(spreadKeysObj.length, 3); +assertEq(spreadKeysObj[0], "a"); +assertEq(spreadKeysObj[1], "x"); +assertEq(spreadKeysObj[2], "y"); + +var i = 0; +for (var key in rec) { + switch (i++) { + case 0: assertEq(key, "a"); break; + case 1: assertEq(key, "x"); break; + case 2: assertEq(key, "y"); break; + default: assertUnreachable(); + } +} + +if (typeof reportCompare === "function") reportCompare(0, 0); diff --git a/js/src/tests/non262/Record/equality.js b/js/src/tests/non262/Record/equality.js new file mode 100644 index 0000000000..6e8665af19 --- /dev/null +++ b/js/src/tests/non262/Record/equality.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty("Record")) + +assertEq(#{} === #{}, true); +assertEq(#{} === #{ x: 1 }, false); +assertEq(#{} === #{ x: undefined }, false); +assertEq(#{ x: 1 } === #{ x: 1 }, true); +assertEq(#{ x: 2 } === #{ x: 1 }, false); +assertEq(#{ y: 1 } === #{ x: 1 }, false); +assertEq(#{ x: 1, y: 2 } === #{ y: 2, x: 1 }, true); +assertEq(#{ x: 1, y: 2 } === #{ y: 1, x: 2 }, false); + +let withPositiveZero = #{ x: +0 }; +let withNegativeZero = #{ x: -0 }; + +assertEq(withPositiveZero === withNegativeZero, true); +assertEq(#[withPositiveZero] === #[withNegativeZero], true); +assertEq(Object.is(withPositiveZero, withNegativeZero), false); +assertEq(Object.is(#[withPositiveZero], #[withNegativeZero]), false); + +assertEq(#{ x: NaN } === #{ x: NaN }, true); +assertEq(Object.is(#{ x: NaN }, #{ x: NaN }), true); + +if (typeof reportCompare === "function") reportCompare(0, 0); diff --git a/js/src/tests/non262/Record/json.js b/js/src/tests/non262/Record/json.js new file mode 100644 index 0000000000..8a327f2eea --- /dev/null +++ b/js/src/tests/non262/Record/json.js @@ -0,0 +1,13 @@ +// |reftest| skip-if(!this.hasOwnProperty("Record")) + +assertEq( + JSON.stringify(#{ x: 1, a: #[1, 2, #{}, #[]] }), + '{"a":[1,2,{},[]],"x":1}' +); + +assertEq( + JSON.stringify({ rec: Object(#{ x: 1 }), tup: Object(#[1, 2]) }), + '{"rec":{"x":1},"tup":[1,2]}' +); + +if (typeof reportCompare === "function") reportCompare(0, 0); diff --git a/js/src/tests/non262/Record/literal.js b/js/src/tests/non262/Record/literal.js new file mode 100644 index 0000000000..f0d9d67e22 --- /dev/null +++ b/js/src/tests/non262/Record/literal.js @@ -0,0 +1,41 @@ +// |reftest| skip-if(!this.hasOwnProperty("Record")) + +let rec = #{ x: 1, "y": 2, 0: 3, 1n: 4, [`key${4}`]: 5 }; + +assertEq(rec.x, 1); +assertEq(rec.y, 2); +assertEq(rec[0], 3); +assertEq(rec[1], 4); +assertEq(rec.key4, 5); + +let dup = #{ x: 1, x: 2 }; +assertEq(dup.x, 2); + +assertThrowsInstanceOf( + () => #{ [Symbol()]: 1 }, + TypeError, + "Symbols cannot be used as record keys" + ); + +let rec2 = #{ x: 1, ...{ a: 2, z: 3 }, b: 4, ...{ d: 5 } }; +assertEq(rec2.x, 1); +assertEq(rec2.a, 2); +assertEq(rec2.z, 3); +assertEq(rec2.b, 4); +assertEq(rec2.d, 5); + +assertThrowsInstanceOf( + () => #{ ...{ [Symbol()]: 1 } }, + TypeError, + "Symbols cannot be used as record keys" +); + +let rec3 = #{ + ...Object.defineProperty({}, "x", { value: 1 }), + ...Object.defineProperty({}, Symbol(), { value: 2 }), +}; +assertEq(rec3.x, undefined); + +let rec4 = #{ ...{}, ...{}, ...{} }; + +if (typeof reportCompare === "function") reportCompare(0, 0); diff --git a/js/src/tests/non262/Record/properties.js b/js/src/tests/non262/Record/properties.js new file mode 100644 index 0000000000..c8139488c0 --- /dev/null +++ b/js/src/tests/non262/Record/properties.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty("Record")) + +var rec = Record({ + x: 1, + 4: 2, + z: 10n ** 100n, + w: Record({}), + n: Tuple(), + [Symbol.iterator]: 4, +}); + +assertEq(rec.x, 1); +assertEq(rec[4], 2); +assertEq(rec.z, 10n ** 100n); +assertEq(typeof rec.w, "record"); +assertEq(typeof rec.n, "tuple"); +assertEq(rec[Symbol.iterator], undefined); +assertEq(rec.hasOwnProperty, undefined); + +if (typeof reportCompare === "function") reportCompare(0, 0); diff --git a/js/src/tests/non262/Record/property-descriptors.js b/js/src/tests/non262/Record/property-descriptors.js new file mode 100644 index 0000000000..fea6187536 --- /dev/null +++ b/js/src/tests/non262/Record/property-descriptors.js @@ -0,0 +1,89 @@ +// |reftest| skip-if(!this.hasOwnProperty("Record")) + +var rec = Record({ x: 1, y: 2, a: 3 }); + +var desc = Object.getOwnPropertyDescriptor(rec, "x"); +assertEq(desc.value, 1); +assertEq(desc.writable, false); +assertEq(desc.enumerable, true); +assertEq(desc.configurable, false); + +assertEq(Object.getOwnPropertyDescriptor(rec, "z"), undefined); + +var recO = Object(rec); + +assertThrowsInstanceOf( + () => Object.defineProperty(rec, "x", { value: 1 }), + TypeError, + "#{ \"a\": 3, \"x\": 1, \"y\": 2 } is not a non-null object" +); + +assertThrowsInstanceOf( + () => Object.defineProperty(recO, "b", {}), + TypeError, + "can't define property \"b\": Record is not extensible" +); + +assertThrowsInstanceOf( + () => Object.defineProperty(recO, Symbol(), {}), + TypeError, + "can't define property \"b\": Record is not extensible" +); + +assertThrowsInstanceOf( + () => Object.defineProperty(recO, "x", { value: 2 }), + TypeError, + '"x" is read-only' +); + +Object.defineProperty(recO, "x", { value: 1 }); + +assertThrowsInstanceOf( + () => Object.defineProperty(recO, "x", { value: 2, writable: true }), + TypeError, + 'Invalid record property descriptor' +); + +assertThrowsInstanceOf( + () => Object.defineProperty(recO, "x", { value: 2, enumerable: false }), + TypeError, + 'Invalid record property descriptor' +); + +assertThrowsInstanceOf( + () => Object.defineProperty(recO, "x", { value: 2, configurable: true }), + TypeError, + 'Invalid record property descriptor' +); + +assertEq(Object.prototype.propertyIsEnumerable.call(rec, "x"), true); +assertEq(Object.prototype.propertyIsEnumerable.call(rec, "x"), true); +assertEq(Object.prototype.propertyIsEnumerable.call(rec, "w"), false); +assertEq(Object.prototype.propertyIsEnumerable.call(rec, "w"), false); +assertEq(Object.prototype.propertyIsEnumerable.call(recO, "x"), true); +assertEq(Object.prototype.propertyIsEnumerable.call(recO, "x"), true); +assertEq(Object.prototype.propertyIsEnumerable.call(recO, "w"), false); +assertEq(Object.prototype.propertyIsEnumerable.call(recO, "w"), false); + +assertEq(Object.prototype.hasOwnProperty.call(rec, "x"), true); +assertEq(Object.prototype.hasOwnProperty.call(rec, "x"), true); +assertEq(Object.prototype.hasOwnProperty.call(rec, "w"), false); +assertEq(Object.prototype.hasOwnProperty.call(rec, "w"), false); +assertEq(Object.prototype.hasOwnProperty.call(recO, "x"), true); +assertEq(Object.prototype.hasOwnProperty.call(recO, "x"), true); +assertEq(Object.prototype.hasOwnProperty.call(recO, "w"), false); +assertEq(Object.prototype.hasOwnProperty.call(recO, "w"), false); + +assertEq("x" in recO, true); +assertEq("w" in recO, false); + +assertEq(delete rec.x, false); +assertEq(delete rec.x, false); +assertEq(delete rec.w, true); +assertEq(delete rec.w, true); +assertEq(delete recO.x, false); +assertEq(delete recO.x, false); +assertEq(delete recO.w, true); +assertEq(delete recO.w, true); + +if (typeof reportCompare === "function") reportCompare(0, 0); diff --git a/js/src/tests/non262/Record/shell.js b/js/src/tests/non262/Record/shell.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Record/syntax.js b/js/src/tests/non262/Record/syntax.js new file mode 100644 index 0000000000..1291cd3bab --- /dev/null +++ b/js/src/tests/non262/Record/syntax.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty("Record")) + +Reflect.parse("#{}"); +Reflect.parse("#{ foo: 1, bar: 2 }"); +Reflect.parse("#{ foo: 1, bar: 2, }"); +Reflect.parse("#{ foo, ...bar }"); +Reflect.parse("#{ foo, ...bar, }"); +Reflect.parse("#{ foo: 1, ...bar, baz: 2 }"); +Reflect.parse("#{ foo }"); +Reflect.parse("#{ foo, }"); +Reflect.parse("#{ foo, bar }"); +Reflect.parse("#{ foo: 1, bar }"); +Reflect.parse("#{ foo, bar: 2 }"); +Reflect.parse("#{ foo: bar() }"); + +Reflect.parse("#{ __proto__ }"); +Reflect.parse("#{ ['__proto__']: 2 }"); + +assertThrowsInstanceOf(() => Reflect.parse("#{,}"), SyntaxError); +assertThrowsInstanceOf(() => Reflect.parse("#{ foo() {} }"), SyntaxError); +assertThrowsInstanceOf(() => Reflect.parse("#{ get foo() {} }"), SyntaxError); +assertThrowsInstanceOf(() => Reflect.parse("#{ __proto__: 2 }"), SyntaxError); +assertThrowsInstanceOf(() => Reflect.parse("#{ '__proto__': 2 }"), SyntaxError); +assertThrowsInstanceOf(() => Reflect.parse("#{ foo = 2 }"), SyntaxError); +assertThrowsInstanceOf(() => Reflect.parse("#{ foo } = bar"), SyntaxError); + +if (typeof reportCompare === "function") reportCompare(0, 0); diff --git a/js/src/tests/non262/Record/wrapper.js b/js/src/tests/non262/Record/wrapper.js new file mode 100644 index 0000000000..1c905739a5 --- /dev/null +++ b/js/src/tests/non262/Record/wrapper.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty("Record")) + +var boxO = Object(#{ x: 1, y: 2 }); + +assertEq(Object.isExtensible(boxO), false); +assertEq(Object.isSealed(boxO), true); +assertEq(Object.isFrozen(boxO), true); + +boxO.x = 3; +assertEq(boxO.x, 1); +assertThrowsInstanceOf(() => { "use strict"; boxO.x = 3; }, TypeError); +assertEq(boxO.x, 1); + +boxO.z = 3; +assertEq(boxO.z, undefined); +assertThrowsInstanceOf(() => { "use strict"; boxO.z = 3; }, TypeError); +assertEq(boxO.z, undefined); + +assertThrowsInstanceOf(() => { Object.defineProperty(boxO, "x", { value: 3 }); }, TypeError); +assertEq(boxO.x, 1); + +assertThrowsInstanceOf(() => { Object.defineProperty(boxO, "z", { value: 3 }); }, TypeError); +assertEq(boxO.z, undefined); + +if (typeof reportCompare === "function") reportCompare(0, 0); diff --git a/js/src/tests/non262/Reflect/apply.js b/js/src/tests/non262/Reflect/apply.js new file mode 100644 index 0000000000..fbd9db2a4b --- /dev/null +++ b/js/src/tests/non262/Reflect/apply.js @@ -0,0 +1,130 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Reflect.apply calls functions. +assertEq(Reflect.apply(Math.floor, undefined, [1.75]), 1); + +// Reflect.apply requires a target object that's callable. +var nonCallable = [{}, [], (class clsX { constructor() {} })]; +for (var value of nonCallable) { + assertThrowsInstanceOf(() => Reflect.apply(nonCallable), TypeError); +} + +// When target is not callable, Reflect.apply does not try to get argumentList.length before throwing. +var hits = 0; +var bogusArgumentList = {get length() { hit++; throw "FAIL";}}; +assertThrowsInstanceOf(() => Reflect.apply({callable: false}, null, bogusArgumentList), + TypeError); +assertEq(hits, 0); + +// Reflect.apply works on a range of different callable objects. +// Builtin functions (we also tested Math.floor above): +assertEq(Reflect.apply(String.fromCharCode, + undefined, + [104, 101, 108, 108, 111]), + "hello"); + +// Builtin methods: +assertEq(Reflect.apply(RegExp.prototype.exec, + /ab/, + ["confabulation"]).index, + 4); + +// Builtin methods of primitive objects: +assertEq(Reflect.apply("".charAt, + "ponies", + [3]), + "i"); + +// Bound functions: +assertEq(Reflect.apply(function () { return this; }.bind(Math), + Function, + []), + Math); +assertEq(Reflect.apply(Array.prototype.concat.bind([1, 2], [3]), + [4, 5], + [[6, 7, 8]]).join(), + "1,2,3,6,7,8"); + +// Generator functions: +function* g(arg) { yield "pass" + arg; } +assertEq(Reflect.apply(g, + undefined, + ["word"]).next().value, + "password"); + +// Proxies: +function f() { return 13; } +assertEq(Reflect.apply(new Proxy(f, {}), + undefined, + []), + 13); + +// Cross-compartment wrappers: +var gw = newGlobal(); +assertEq(Reflect.apply(gw.parseInt, + undefined, + ["45"]), + 45); +assertEq(Reflect.apply(gw.Symbol.for, + undefined, + ["moon"]), + Symbol.for("moon")); + +gw.eval("function q() { return q; }"); +assertEq(Reflect.apply(gw.q, + undefined, + []), + gw.q); + + +// Exceptions are propagated. +var nope = new Error("nope"); +function fail() { + throw nope; +} +assertThrowsValue(() => Reflect.apply(fail, undefined, []), + nope); + +// Exceptions thrown by cross-compartment wrappers are re-wrapped for the +// calling compartment. +var gxw = gw.eval("var x = new Error('x'); x"); +gw.eval("function fail() { throw x; }"); +assertThrowsValue(() => Reflect.apply(gw.fail, undefined, []), + gxw); + +// The thisArgument is passed to the target function as the 'this' value. +var obj = {}; +hits = 0; +assertEq(Reflect.apply(function () { hits++; assertEq(this, obj); }, + obj, + []), + undefined); +assertEq(hits, 1); + +// Primitive values can be thisArgument. +function strictThis() { "use strict"; return this; } +for (var value of [null, undefined, 0, -0, NaN, Symbol("moon")]) { + assertEq(Reflect.apply(strictThis, value, []), + value); +} + +// If the target is a non-strict function and thisArgument is a primitive value +// other than null or undefined, then thisArgument is converted to a wrapper +// object. +var testValues = [true, 1e9, "ok", Symbol("ok")]; +function nonStrictThis(expected) { + assertEq(typeof this, "object"); + assertEq(Reflect.apply(Object.prototype.toString, this, []).toLowerCase(), expected); + return "ok"; +} +for (var value of testValues) { + assertEq(Reflect.apply(nonStrictThis, + value, + ["[object " + typeof value + "]"]), + "ok"); +} + +// For more Reflect.apply tests, see target.js and argumentsList.js. + +reportCompare(0, 0); diff --git a/js/src/tests/non262/Reflect/argumentsList.js b/js/src/tests/non262/Reflect/argumentsList.js new file mode 100644 index 0000000000..1cd5984f00 --- /dev/null +++ b/js/src/tests/non262/Reflect/argumentsList.js @@ -0,0 +1,164 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Tests for the argumentList argument to Reflect.apply and Reflect.construct. + +// Reflect.apply and Reflect.construct require an argumentList argument that must be an object. +assertThrowsInstanceOf(() => Reflect.apply(Math.min, undefined), // missing + TypeError); +assertThrowsInstanceOf(() => Reflect.construct(Object), // missing + TypeError); +for (var primitive of SOME_PRIMITIVE_VALUES) { + assertThrowsInstanceOf(() => Reflect.apply(Math.min, undefined, primitive), + TypeError); + assertThrowsInstanceOf(() => Reflect.construct(Object, primitive), + TypeError); +} + +// Array used by several tests below. +var BOTH = [ + Reflect.apply, + // Adapt Reflect.construct to accept the same arguments as Reflect.apply. + (target, thisArgument, argumentList) => Reflect.construct(target, argumentList) +]; + +// The argumentList is copied and becomes the list of arguments passed to the function. +function getRest(...x) { return x; } +var args = [1, 2, 3]; +for (var method of BOTH) { + var result = method(getRest, undefined, args); + assertEq(result.join(), args.join()); + assertEq(result !== args, true); +} + +// argumentList.length can be less than func.length. +function testLess(a, b, c, d, e) { + assertEq(a, 1); + assertEq(b, true); + assertEq(c, "three"); + assertEq(d, Symbol.for); + assertEq(e, undefined); + + assertEq(arguments.length, 4); + assertEq(arguments !== args, true); + return "ok"; +} +args = [1, true, "three", Symbol.for]; +assertEq(Reflect.apply(testLess, undefined, args), "ok"); +assertEq(Reflect.construct(testLess, args) instanceof testLess, true); + +// argumentList.length can be more than func.length. +function testMoar(a) { + assertEq(a, args[0]); + return "good"; +} +assertEq(Reflect.apply(testMoar, undefined, args), "good"); +assertEq(Reflect.construct(testMoar, args) instanceof testMoar, true); + +// argumentList can be any object with a .length property. +function getArgs(...args) { + return args; +} +for (var method of BOTH) { + assertDeepEq(method(getArgs, undefined, {length: 0}), + []); + assertDeepEq(method(getArgs, undefined, {length: 1, "0": "zero"}), + ["zero"]); + assertDeepEq(method(getArgs, undefined, {length: 2}), + [undefined, undefined]); + assertDeepEq(method(getArgs, undefined, function (a, b, c) {}), + [undefined, undefined, undefined]); +} + +// The Iterable/Iterator interfaces are not used. +var funnyArgs = { + 0: "zero", + 1: "one", + length: 2, + [Symbol.iterator]() { throw "FAIL 1"; }, + next() { throw "FAIL 2"; } +}; +for (var method of BOTH) { + assertDeepEq(method(getArgs, undefined, funnyArgs), + ["zero", "one"]); +} + +// If argumentList has no .length property, no arguments are passed. +function count() { return {numArgsReceived: arguments.length}; } +for (var method of BOTH) { + assertEq(method(count, undefined, {"0": 0, "1": 1}).numArgsReceived, + 0); + function* g() { yield 1; yield 2; } + assertEq(method(count, undefined, g()).numArgsReceived, + 0); +} + +// If argumentsList.length has a getter, it is called. +var log; +args = { + get length() { log += "L"; return 1; }, + get "0"() { log += "0"; return "zero"; }, + get "1"() { log += "1"; return "one"; } +}; +for (var method of BOTH) { + log = ""; + assertDeepEq(method(getArgs, undefined, args), + ["zero"]); + assertEq(log, "L0"); +} + +// The argumentsList.length getter can throw; the exception is propagated. +var exc = {status: "bad"}; +args = { + get length() { throw exc; } +}; +for (var method of BOTH) { + assertThrowsValue(() => method(count, undefined, args), exc); +} + +// If argumentsList.length is unreasonably huge, we get an error. +// (This is an implementation limit.) +for (var method of BOTH) { + for (var value of [1e12, 1e240, Infinity]) { + assertThrowsInstanceOf(() => method(count, undefined, {length: value}), + Error); + } +} + +// argumentsList.length is converted to an integer. +for (var value of [1.7, "1", {valueOf() { return "1"; }}]) { + args = { + length: value, + "0": "ponies" + }; + for (var method of BOTH) { + var result = method(getArgs, undefined, args); + assertEq(result.length, 1); + assertEq(result[0], "ponies"); + } +} + +// If argumentsList.length is negative or NaN, no arguments are passed. +for (var method of BOTH) { + for (var num of [-1, -0.1, -0, -1e99, -Infinity, NaN]) { + assertEq(method(count, undefined, {length: num}).numArgsReceived, + 0); + } +} + +// Many arguments can be passed. +var many = 65537; +var args = {length: many, 0: "zero", [many - 1]: "last"}; +function testMany(...args) { + for (var i = 0; i < many; i++) { + assertEq(i in args, true); + assertEq(args[i], i === 0 ? "zero" : i === many - 1 ? "last" : undefined); + } + return this; +} +assertEq(Reflect.apply(testMany, "pass", args).toString(), "pass"); +assertEq(Reflect.construct(testMany, args) instanceof testMany, true); +assertEq(Reflect.apply(new Proxy(testMany, {}), "pass", args).toString(), "pass"); +assertEq(Reflect.construct(new Proxy(testMany, {}), args) instanceof testMany, true); + +reportCompare(0, 0); diff --git a/js/src/tests/non262/Reflect/browser.js b/js/src/tests/non262/Reflect/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Reflect/construct.js b/js/src/tests/non262/Reflect/construct.js new file mode 100644 index 0000000000..7dbb9bfa7d --- /dev/null +++ b/js/src/tests/non262/Reflect/construct.js @@ -0,0 +1,107 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Reflect.construct invokes constructors. + +assertDeepEq(Reflect.construct(Object, []), {}); +assertDeepEq(Reflect.construct(String, ["hello"]), new String("hello")); + +// Constructing Date creates a real Date object. +var d = Reflect.construct(Date, [1776, 6, 4]); +assertEq(d instanceof Date, true); +assertEq(d.getFullYear(), 1776); // non-generic method requires real Date object + +// [[Construct]] methods don't necessarily create new objects. +var obj = {}; +assertEq(Reflect.construct(Object, [obj]), obj); + + +// === Various kinds of constructors +// We've already seen some builtin constructors. +// +// JS functions: +function f(x) { this.x = x; } +assertDeepEq(Reflect.construct(f, [3]), new f(3)); +f.prototype = Array.prototype; +assertDeepEq(Reflect.construct(f, [3]), new f(3)); + +// Bound functions: +var bound = f.bind(null, "carrot"); +assertDeepEq(Reflect.construct(bound, []), new bound); + +// Classes: +class Base { + constructor(...args) { + this.args = args; + this.newTarget = new.target; + } +} +class Derived extends Base { + constructor(...args) { super(...args); } +} + +assertDeepEq(Reflect.construct(Base, []), new Base); +assertDeepEq(Reflect.construct(Derived, [7]), new Derived(7)); +g = Derived.bind(null, "q"); +assertDeepEq(Reflect.construct(g, [8, 9]), new g(8, 9)); + +// Cross-compartment wrappers: +var g = newGlobal(); +var local = {here: this}; +g.eval("function F(arg) { this.arg = arg }"); +assertDeepEq(Reflect.construct(g.F, [local]), new g.F(local)); + +// If first argument to Reflect.construct isn't a constructor, it throws a +// TypeError. +var nonConstructors = [ + {}, + Reflect.construct, // builtin functions aren't constructors + x => x + 1, + Math.max.bind(null, 0), // bound non-constructors aren't constructors + ((x, y) => x > y).bind(null, 0), + + // A Proxy to a non-constructor function isn't a constructor, even if a + // construct handler is present. + new Proxy(Reflect.construct, {construct(){}}), +]; +for (var obj of nonConstructors) { + assertThrowsInstanceOf(() => Reflect.construct(obj, []), TypeError); + assertThrowsInstanceOf(() => Reflect.construct(obj, [], Object), TypeError); +} + + +// === new.target tests + +// If the newTarget argument to Reflect.construct is missing, the target is used. +function checkNewTarget() { + assertEq(new.target, expected); + expected = undefined; +} +var expected = checkNewTarget; +Reflect.construct(checkNewTarget, []); + +// The newTarget argument is correctly passed to the constructor. +var constructors = [Object, Function, f, bound]; +for (var ctor of constructors) { + expected = ctor; + Reflect.construct(checkNewTarget, [], ctor); + assertEq(expected, undefined); +} + +// The newTarget argument must be a constructor. +for (var v of SOME_PRIMITIVE_VALUES.concat(nonConstructors)) { + assertThrowsInstanceOf(() => Reflect.construct(checkNewTarget, [], v), TypeError); +} + +// The builtin Array constructor uses new.target.prototype and always +// creates a real array object. +function someConstructor() {} +var result = Reflect.construct(Array, [], someConstructor); +assertEq(Reflect.getPrototypeOf(result), someConstructor.prototype); +assertEq(result.length, 0); +assertEq(Array.isArray(result), true); + + +// For more Reflect.construct tests, see target.js and argumentsList.js. + +reportCompare(0, 0); diff --git a/js/src/tests/non262/Reflect/defineProperty.js b/js/src/tests/non262/Reflect/defineProperty.js new file mode 100644 index 0000000000..1f299f4e85 --- /dev/null +++ b/js/src/tests/non262/Reflect/defineProperty.js @@ -0,0 +1,164 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Reflect.defineProperty defines properties. +var obj = {}; +assertEq(Reflect.defineProperty(obj, "x", {value: 7}), true); +assertEq(obj.x, 7); +var desc = Reflect.getOwnPropertyDescriptor(obj, "x"); +assertDeepEq(desc, {value: 7, + writable: false, + enumerable: false, + configurable: false}); + +// Reflect.defineProperty can define a symbol-keyed property. +var key = Symbol(":o)"); +assertEq(Reflect.defineProperty(obj, key, {value: 8}), true); +assertEq(obj[key], 8); + +// array .length property +obj = [1, 2, 3, 4, 5]; +assertEq(Reflect.defineProperty(obj, "length", {value: 4}), true); +assertDeepEq(obj, [1, 2, 3, 4]); + +// The target can be a proxy. +obj = {}; +var proxy = new Proxy(obj, { + defineProperty(t, id, desc) { + t[id] = 1; + return true; + } +}); +assertEq(Reflect.defineProperty(proxy, "prop", {value: 7}), true); +assertEq(obj.prop, 1); +assertEq(delete obj.prop, true); +assertEq("prop" in obj, false); + +// The attributes object is re-parsed, not passed through to the +// handler.defineProperty method. +obj = {}; +var attributes = { + configurable: 17, + enumerable: undefined, + value: null +}; +proxy = new Proxy(obj, { + defineProperty(t, id, desc) { + assertEq(desc !== attributes, true); + assertEq(desc.configurable, true); + assertEq(desc.enumerable, false); + assertEq(desc.value, null); + assertEq("writable" in desc, false); + return 15; // and the return value here is coerced to boolean + } +}); +assertEq(Reflect.defineProperty(proxy, "prop", attributes), true); + + +// === Failure and error cases +// +// Reflect.defineProperty behaves much like Object.defineProperty, which has +// extremely thorough tests elsewhere, and the implementation is largely +// shared. Duplicating those tests with Reflect.defineProperty would be a +// big waste. +// +// However, certain failures cause Reflect.defineProperty to return false +// without throwing a TypeError (unlike Object.defineProperty). So here we test +// many error cases to check that behavior. + +// missing attributes argument +assertThrowsInstanceOf(() => Reflect.defineProperty(obj, "y"), + TypeError); + +// non-object attributes argument +for (var attributes of SOME_PRIMITIVE_VALUES) { + assertThrowsInstanceOf(() => Reflect.defineProperty(obj, "y", attributes), + TypeError); +} + +// inextensible object +obj = Object.preventExtensions({}); +assertEq(Reflect.defineProperty(obj, "prop", {value: 4}), false); + +// inextensible object with irrelevant inherited property +obj = Object.preventExtensions(Object.create({"prop": 3})); +assertEq(Reflect.defineProperty(obj, "prop", {value: 4}), false); + +// redefine nonconfigurable to configurable +obj = Object.freeze({prop: 1}); +assertEq(Reflect.defineProperty(obj, "prop", {configurable: true}), false); + +// redefine enumerability of nonconfigurable property +obj = Object.freeze(Object.defineProperties({}, { + x: {enumerable: true, configurable: false, value: 0}, + y: {enumerable: false, configurable: false, value: 0}, +})); +assertEq(Reflect.defineProperty(obj, "x", {enumerable: false}), false); +assertEq(Reflect.defineProperty(obj, "y", {enumerable: true}), false); + +// redefine nonconfigurable data to accessor property, or vice versa +obj = Object.seal({x: 1, get y() { return 2; }}); +assertEq(Reflect.defineProperty(obj, "x", {get() { return 2; }}), false); +assertEq(Reflect.defineProperty(obj, "y", {value: 1}), false); + +// redefine nonwritable, nonconfigurable property as writable +obj = Object.freeze({prop: 0}); +assertEq(Reflect.defineProperty(obj, "prop", {writable: true}), false); +assertEq(Reflect.defineProperty(obj, "prop", {writable: false}), true); // no-op + +// change value of nonconfigurable nonwritable property +obj = Object.freeze({prop: 0}); +assertEq(Reflect.defineProperty(obj, "prop", {value: -0}), false); +assertEq(Reflect.defineProperty(obj, "prop", {value: +0}), true); // no-op + +// change getter or setter +function g() {} +function s(x) {} +obj = {}; +Object.defineProperty(obj, "prop", {get: g, set: s, configurable: false}); +assertEq(Reflect.defineProperty(obj, "prop", {get: s}), false); +assertEq(Reflect.defineProperty(obj, "prop", {get: g}), true); // no-op +assertEq(Reflect.defineProperty(obj, "prop", {set: g}), false); +assertEq(Reflect.defineProperty(obj, "prop", {set: s}), true); // no-op + +// Proxy defineProperty handler method that returns false +var falseValues = [false, 0, -0, "", NaN, null, undefined]; +if (typeof createIsHTMLDDA === "function") + falseValues.push(createIsHTMLDDA()); +var value; +proxy = new Proxy({}, { + defineProperty(t, id, desc) { + return value; + } +}); +for (value of falseValues) { + assertEq(Reflect.defineProperty(proxy, "prop", {value: 1}), false); +} + +// Proxy defineProperty handler method returns true, in violation of invariants. +// Per spec, this is a TypeError, not a false return. +obj = Object.freeze({x: 1}); +proxy = new Proxy(obj, { + defineProperty(t, id, desc) { + return true; + } +}); +assertThrowsInstanceOf(() => Reflect.defineProperty(proxy, "x", {value: 2}), TypeError); +assertThrowsInstanceOf(() => Reflect.defineProperty(proxy, "y", {value: 0}), TypeError); +assertEq(Reflect.defineProperty(proxy, "x", {value: 1}), true); + +// The second argument is converted ToPropertyKey before any internal methods +// are called on the first argument. +var poison = + (counter => new Proxy({}, new Proxy({}, { get() { throw counter++; } })))(42); +assertThrowsValue(() => { + Reflect.defineProperty(poison, { + toString() { throw 17; }, + valueOf() { throw 8675309; } + }, poison); +}, 17); + + +// For more Reflect.defineProperty tests, see target.js and propertyKeys.js. + +reportCompare(0, 0); diff --git a/js/src/tests/non262/Reflect/deleteProperty.js b/js/src/tests/non262/Reflect/deleteProperty.js new file mode 100644 index 0000000000..744e0f5715 --- /dev/null +++ b/js/src/tests/non262/Reflect/deleteProperty.js @@ -0,0 +1,80 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Reflect.deleteProperty deletes properties. +var obj = {x: 1, y: 2}; +assertEq(Reflect.deleteProperty(obj, "x"), true); +assertDeepEq(obj, {y: 2}); + +var arr = [1, 1, 2, 3, 5]; +assertEq(Reflect.deleteProperty(arr, "3"), true); +assertDeepEq(arr, [1, 1, 2, , 5]); + + +// === Failure and error cases +// Since Reflect.deleteProperty is almost exactly identical to the non-strict +// `delete` operator, there is not much to test that would not be redundant. + +// Returns true if no such property exists. +assertEq(Reflect.deleteProperty({}, "q"), true); + +// Or if it's inherited. +var proto = {x: 1}; +assertEq(Reflect.deleteProperty(Object.create(proto), "x"), true); +assertEq(proto.x, 1); + +// Return false if asked to delete a non-configurable property. +var arr = []; +assertEq(Reflect.deleteProperty(arr, "length"), false); +assertEq(arr.hasOwnProperty("length"), true); +assertEq(Reflect.deleteProperty(this, "undefined"), false); +assertEq(this.undefined, void 0); + +// Return false if a Proxy's deleteProperty handler returns a false-y value. +var value; +var proxy = new Proxy({}, { + deleteProperty(t, k) { + return value; + } +}); +for (value of [true, false, 0, "something", {}]) { + assertEq(Reflect.deleteProperty(proxy, "q"), !!value); +} + +// If a Proxy's handler method throws, the error is propagated. +proxy = new Proxy({}, { + deleteProperty(t, k) { throw "vase"; } +}); +assertThrowsValue(() => Reflect.deleteProperty(proxy, "prop"), "vase"); + +// Throw a TypeError if a Proxy's handler method returns true in violation of +// the object invariants. +proxy = new Proxy(Object.freeze({prop: 1}), { + deleteProperty(t, k) { return true; } +}); +assertThrowsInstanceOf(() => Reflect.deleteProperty(proxy, "prop"), TypeError); + + +// === Deleting elements from `arguments` + +// Non-strict arguments element becomes unmapped +function f(x, y, z) { + assertEq(Reflect.deleteProperty(arguments, "0"), true); + arguments.x = 33; + return x; +} +assertEq(f(17, 19, 23), 17); + +// Frozen non-strict arguments element +function testFrozenArguments() { + Object.freeze(arguments); + assertEq(Reflect.deleteProperty(arguments, "0"), false); + assertEq(arguments[0], "zero"); + assertEq(arguments[1], "one"); +} +testFrozenArguments("zero", "one"); + + +// For more Reflect.deleteProperty tests, see target.js and propertyKeys.js. + +reportCompare(0, 0); diff --git a/js/src/tests/non262/Reflect/get.js b/js/src/tests/non262/Reflect/get.js new file mode 100644 index 0000000000..b38b188b03 --- /dev/null +++ b/js/src/tests/non262/Reflect/get.js @@ -0,0 +1,72 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Reflect.get gets the value of a property. + +var x = {p: 1}; +assertEq(Reflect.get(x, "p"), 1); +assertEq(Reflect.get(x, "toString"), Object.prototype.toString); +assertEq(Reflect.get(x, "missing"), undefined); + + +// === Various targets + +// Array +assertEq(Reflect.get([], 700), undefined); +assertEq(Reflect.get(["zero", "one"], 1), "one"); + +// TypedArray +assertEq(Reflect.get(new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7]), 7), 7); + +// Treatment of NaN +var f = new Float64Array([NaN]); +var u = new Uint32Array(f.buffer); +u[0]++; +u[1]++; +assertEq(f[0], NaN); +assertEq(Reflect.get(f, 0), NaN); + +// Proxy with no get handler +assertEq(Reflect.get(new Proxy(x, {}), "p"), 1); + +// Proxy with a get handler +var obj = new Proxy(x, { + get(t, k, r) { return k + "ful"; } +}); +assertEq(Reflect.get(obj, "mood"), "moodful"); + +// Exceptions thrown by a proxy's get handler are propagated. +assertThrowsInstanceOf(() => Reflect.get(obj, Symbol()), TypeError); + +// Ordinary object, property has a setter and no getter +obj = {set name(x) {}}; +assertEq(Reflect.get(obj, "name"), undefined); + + +// === Receiver + +// Receiver argument is passed to getters as the this-value. +obj = { get x() { return this; }}; +assertEq(Reflect.get(obj, "x", Math), Math); +assertEq(Reflect.get(Object.create(obj), "x", JSON), JSON); + +// If missing, target is passed instead. +assertEq(Reflect.get(obj, "x"), obj); + +// Receiver argument is passed to the proxy get handler. +obj = new Proxy({}, { + get(t, k, r) { + assertEq(k, "itself"); + return r; + } +}); +assertEq(Reflect.get(obj, "itself"), obj); +assertEq(Reflect.get(obj, "itself", Math), Math); +assertEq(Reflect.get(Object.create(obj), "itself", Math), Math); + +// The receiver shouldn't have to be an object +assertEq(Reflect.get(obj, "itself", 37.2), 37.2); + +// For more Reflect.get tests, see target.js and propertyKeys.js. + +reportCompare(0, 0); diff --git a/js/src/tests/non262/Reflect/getOwnPropertyDescriptor.js b/js/src/tests/non262/Reflect/getOwnPropertyDescriptor.js new file mode 100644 index 0000000000..aa7329778d --- /dev/null +++ b/js/src/tests/non262/Reflect/getOwnPropertyDescriptor.js @@ -0,0 +1,21 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Reflect.getOwnPropertyDescriptor inspects object properties. +assertDeepEq( + Reflect.getOwnPropertyDescriptor({x: "hello"}, "x"), + {value: "hello", writable: true, enumerable: true, configurable: true}); +assertEq( + Reflect.getOwnPropertyDescriptor({x: "hello"}, "y"), + undefined); +assertDeepEq( + Reflect.getOwnPropertyDescriptor([], "length"), + {value: 0, writable: true, enumerable: false, configurable: false}); + +// Reflect.getOwnPropertyDescriptor shares its implementation with +// Object.getOwnPropertyDescriptor. The only difference is how non-object +// targets are handled. +// +// For more Reflect.getOwnPropertyDescriptor tests, see target.js and propertyKeys.js. + +reportCompare(0, 0); diff --git a/js/src/tests/non262/Reflect/getPrototypeOf.js b/js/src/tests/non262/Reflect/getPrototypeOf.js new file mode 100644 index 0000000000..6a29d4a9b2 --- /dev/null +++ b/js/src/tests/non262/Reflect/getPrototypeOf.js @@ -0,0 +1,17 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Reflect.getPrototypeOf returns an object's prototype. +assertEq(Reflect.getPrototypeOf({}), Object.prototype); +assertEq(Reflect.getPrototypeOf(Object.prototype), null); +assertEq(Reflect.getPrototypeOf(Object.create(null)), null); + +var proxy = new Proxy({}, { + getPrototypeOf(t) { return Math; } +}); + +assertEq(Reflect.getPrototypeOf(proxy), Math); + +// For more Reflect.getPrototypeOf tests, see target.js. + +reportCompare(0, 0); diff --git a/js/src/tests/non262/Reflect/has.js b/js/src/tests/non262/Reflect/has.js new file mode 100644 index 0000000000..6019a61ed3 --- /dev/null +++ b/js/src/tests/non262/Reflect/has.js @@ -0,0 +1,41 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Reflect.has is identical to the `in` operator. +assertEq(Reflect.has({x: 0}, "x"), true); +assertEq(Reflect.has({x: 0}, "y"), false); +assertEq(Reflect.has({x: 0}, "toString"), true); + +// The target can be an array; Reflect.has works on array elements. +var arr = ["zero"]; +arr[10000] = 0; +assertEq(Reflect.has(arr, "10000"), true); +assertEq(Reflect.has(arr, 10000), true); +assertEq(Reflect.has(arr, "-0"), false); +assertEq(Reflect.has(arr, -0), true); + +// And string objects (though not string primitives; see target.js). +var str = new String("hello"); +assertEq(Reflect.has(str, "4"), true); +assertEq(Reflect.has(str, "-0"), false); +assertEq(Reflect.has(str, -0), true); + +// Proxy without .has() handler method +var obj = {get prop() {}}; +for (var i = 0; i < 2; i++) { + obj = new Proxy(obj, {}); + assertEq(Reflect.has(obj, "prop"), true); + assertEq(Reflect.has(obj, "nope"), false); +} + +// Proxy with .has() handler method +obj = new Proxy({}, { + has(t, k) { return k.startsWith("door"); } +}); +assertEq(Reflect.has(obj, "doorbell"), true); +assertEq(Reflect.has(obj, "dormitory"), false); + + +// For more Reflect.has tests, see target.js and propertyKeys.js. + +reportCompare(0, 0); diff --git a/js/src/tests/non262/Reflect/isExtensible.js b/js/src/tests/non262/Reflect/isExtensible.js new file mode 100644 index 0000000000..f38724875d --- /dev/null +++ b/js/src/tests/non262/Reflect/isExtensible.js @@ -0,0 +1,57 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Reflect.isExtensible behaves just like Object.extensible except when the +// target argument is missing or is not an object (and that behavior is tested +// in target.js). + +// Test basic functionality. +var someObjects = [ + {}, + {a: "a"}, + [0, 1], + new Uint8Array(64), + Object(Symbol("table")), + new Proxy({}, {}) +]; +if (typeof SharedArrayBuffer != "undefined") + someObjects.push(new Uint8Array(new SharedArrayBuffer(64))); + +for (var obj of someObjects) { + assertEq(Reflect.isExtensible(obj), true); + assertEq(Reflect.preventExtensions(obj), true); + assertEq(Reflect.isExtensible(obj), false); +} + +// Array with nonwritable length. +var arr = [0, 1, 2, 3]; +Object.defineProperty(arr, "length", {writable: false}); +assertEq(Reflect.isExtensible(arr), true); + +// Proxy case. +for (var ext of [true, false]) { + var obj = {}; + if (!ext) + Object.preventExtensions(obj); + var proxy = new Proxy(obj, { + isExtensible() { return ext; } + }); + assertEq(Reflect.isExtensible(proxy), ext); +} + +// If a Proxy's isExtensible method throws, the exception is propagated. +proxy = new Proxy({}, { + isExtensible() { throw "oops"; } +}); +assertThrowsValue(() => Reflect.isExtensible(proxy), "oops"); + +// If an invariant is broken, [[IsExtensible]] does not return false. It throws +// a TypeError. +proxy = new Proxy({}, { + isExtensible() { return false; } +}); +assertThrowsInstanceOf(() => Reflect.isExtensible(proxy), TypeError); + +// For more Reflect.isExtensible tests, see target.js. + +reportCompare(0, 0); diff --git a/js/src/tests/non262/Reflect/ownKeys.js b/js/src/tests/non262/Reflect/ownKeys.js new file mode 100644 index 0000000000..5433562eb5 --- /dev/null +++ b/js/src/tests/non262/Reflect/ownKeys.js @@ -0,0 +1,66 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Reflect.ownKeys(obj) returns an array of an object's own property keys. + +// Test that Reflect.ownKeys gets the expected result when applied to various +// objects. (These tests also check the basics: that the result is an array, +// that its prototype is correct, etc.) +var sym = Symbol.for("comet"); +var sym2 = Symbol.for("meteor"); +var cases = [ + {object: {z: 3, y: 2, x: 1}, + keys: ["z", "y", "x"]}, + {object: [], + keys: ["length"]}, + {object: new Int8Array(4), + keys: ["0", "1", "2", "3"]}, + {object: new Proxy({a: 7}, {}), + keys: ["a"]}, + {object: {[sym]: "ok"}, + keys: [sym]}, + {object: {[sym]: 0, // test 9.1.12 ordering + "str": 0, + "773": 0, + "0": 0, + [sym2]: 0, + "-1": 0, + "8": 0, + "second str": 0}, + keys: ["0", "8", "773", // indexes in numeric order + "str", "-1", "second str", // strings in insertion order + sym, sym2]}, // symbols in insertion order + {object: newGlobal().Math, // cross-compartment wrapper + keys: Reflect.ownKeys(Math)} +]; +for (var {object, keys} of cases) + assertDeepEq(Reflect.ownKeys(object), keys); + +// Reflect.ownKeys() creates a new array each time it is called. +var object = {}, keys = []; +for (var i = 0; i < 3; i++) { + var newKeys = Reflect.ownKeys(object); + assertEq(newKeys !== keys, true); + keys = newKeys; +} + +// Proxy behavior with successful ownKeys() handler +keys = ["str", "0"]; +obj = {}; +proxy = new Proxy(obj, { + ownKeys() { return keys; } +}); +var actual = Reflect.ownKeys(proxy); +assertDeepEq(actual, keys); // we get correct answers +assertEq(actual !== keys, true); // but not the same object + +// If a proxy breaks invariants, a TypeError is thrown. +var obj = Object.preventExtensions({}); +var proxy = new Proxy(obj, { + ownKeys() { return ["something"]; } +}); +assertThrowsInstanceOf(() => Reflect.ownKeys(proxy), TypeError); + +// For more Reflect.ownKeys tests, see target.js. + +reportCompare(0, 0); diff --git a/js/src/tests/non262/Reflect/preventExtensions.js b/js/src/tests/non262/Reflect/preventExtensions.js new file mode 100644 index 0000000000..63ca2545b4 --- /dev/null +++ b/js/src/tests/non262/Reflect/preventExtensions.js @@ -0,0 +1,56 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Reflect.preventExtensions is the same as Object.preventExtensions, except +// for the return value and the behavior in error cases. + +var someObjects = [ + {}, + new Int32Array(7), + Object(Symbol("table")), + new Proxy({}, {}) +]; + +for (var obj of someObjects) { + assertEq(Reflect.preventExtensions(obj), true); + // [[PreventExtensions]] on an already-inextensible object is a no-op. + assertEq(Reflect.preventExtensions(obj), true); +} + +// Error cases. +assertThrowsInstanceOf(() => Reflect.isExtensible(), TypeError); +for (var value of [undefined, null, true, 1, NaN, "Phaedo", Symbol("good")]) { + assertThrowsInstanceOf(() => Reflect.isExtensible(value), TypeError); +} + +// A proxy's preventExtensions handler can return false without doing anything. +obj = {}; +var proxy = new Proxy(obj, { + preventExtensions() { return false; } +}); +assertEq(Reflect.preventExtensions(proxy), false); +assertEq(Reflect.isExtensible(obj), true); +assertEq(Reflect.isExtensible(proxy), true); + +// If a proxy's preventExtensions handler throws, the exception is propagated. +obj = {}; +proxy = new Proxy(obj, { + preventExtensions() { throw "fit"; } +}); +assertThrowsValue(() => Reflect.preventExtensions(proxy), "fit"); +assertEq(Reflect.isExtensible(obj), true); +assertEq(Reflect.isExtensible(proxy), true); + +// If a proxy's preventExtensions handler returns true while leaving the target +// extensible, that's a TypeError. +obj = {}; +proxy = new Proxy(obj, { + preventExtensions() { return true; } +}); +assertThrowsInstanceOf(() => Reflect.preventExtensions(proxy), TypeError); +assertEq(Reflect.isExtensible(obj), true); +assertEq(Reflect.isExtensible(proxy), true); + +// For more Reflect.preventExtensions tests, see target.js. + +reportCompare(0, 0); diff --git a/js/src/tests/non262/Reflect/propertyKeys.js b/js/src/tests/non262/Reflect/propertyKeys.js new file mode 100644 index 0000000000..6495a96fd9 --- /dev/null +++ b/js/src/tests/non262/Reflect/propertyKeys.js @@ -0,0 +1,84 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Test corner cases involving Reflect methods' propertyKey arguments. + +// keys - Array of propertyKey values to be tested. +// +// Each element of this array is a record with these properties: +// +// * value: a value that will be passed as a property key +// to the various Reflect methods; +// +// * expected: (optional) the string or symbol that ToPropertyKey(value) +// should return. If this is omitted, ToPropertyKey(value) === value. +// +var keys = [ + {value: null, expected: "null"}, + {value: undefined, expected: "undefined"}, + {value: true, expected: "true"}, + {value: 42, expected: "42"}, + {value: "string"}, + {value: ""}, + {value: "string with \0"}, + {value: new String("ok"), expected: "ok"}, + {value: Symbol("sym")}, + {value: Symbol.iterator}, + {value: Object(Symbol.for("comet")), expected: Symbol.for("comet")}, + { + value: { + toString() { return "key"; }, + valueOf() { return "bad"; } + }, + expected: "key" + }, + { + value: { + toString: undefined, + valueOf() { return "fallback"; } + }, + expected: "fallback" + }, + { + value: { + [Symbol.toPrimitive](hint) { return hint; } + }, + expected: "string" + }, + { + value: { + [Symbol.toPrimitive](hint) { return Symbol.for(hint); } + }, + expected: Symbol.for("string") + } +]; + +for (var {value, expected} of keys) { + if (expected === undefined) + expected = value; + + var obj = {}; + assertEq(Reflect.defineProperty(obj, value, {value: 1, configurable: true}), true); + assertDeepEq(Reflect.ownKeys(obj), [expected]); + assertDeepEq(Reflect.getOwnPropertyDescriptor(obj, value), + {value: 1, + writable: false, + enumerable: false, + configurable: true}); + assertEq(Reflect.deleteProperty(obj, value), true); + assertEq(Reflect.has(obj, value), false); + assertEq(Reflect.set(obj, value, 113), true); + assertEq(obj[expected], 113); + assertEq(Reflect.has(obj, value), true); + assertEq(Reflect.get(obj, value), 113); +} + +// ToPropertyKey can throw. +var exc = {}; +var badKey = {toString() { throw exc; }}; +var methodNames = ["defineProperty", "deleteProperty", "has", "get", "getOwnPropertyDescriptor", "set"]; +for (var name of methodNames) { + assertThrowsValue(() => Reflect[name]({}, badKey), exc); +} + +reportCompare(0, 0); diff --git a/js/src/tests/non262/Reflect/set.js b/js/src/tests/non262/Reflect/set.js new file mode 100644 index 0000000000..83cd98b691 --- /dev/null +++ b/js/src/tests/non262/Reflect/set.js @@ -0,0 +1,280 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Reflect.set does property assignment. +// With three arguments, this is pretty straightforward. +var obj = {}; +assertEq(Reflect.set(obj, "prop", "value"), true); +assertEq(obj.prop, "value"); + + +// === Various targets + +// It can assign array elements. +var arr = ["duck", "duck", "duck"]; +assertEq(Reflect.set(arr, 2, "goose"), true); +assertEq(arr[2], "goose"); + +// It can extend an array. +assertEq(Reflect.set(arr, 3, "Model T"), true); +assertEq(arr.length, 4); + +// It can truncate an array. +assertEq(Reflect.set(arr, "length", 1), true); +assertDeepEq(arr, ["duck"]); + +// It won't assign to non-writable properties of String objects. +var str = new String("hello"); +assertEq(Reflect.set(str, "0", "y"), false); +assertEq(str[0], "h"); +assertEq(Reflect.set(str, "length", 700), false); +assertEq(str.length, 5); + + +// === Receivers +// The optional fourth argument is the receiver, which [[Set]] methods use for +// various things. + +// On ordinary objects, if the property has a setter, the receiver is passed as +// the this-value to the setter. +var expected; +var obj = { + set prop(v) { + "use strict"; + assertEq(v, 32); + assertEq(this, expected); + } +}; +for (expected of [obj, {}, [], 37.3]) { + assertEq(Reflect.set(obj, "prop", 32, expected), true); +} + +// If the property doesn't already exist, it is defined on the receiver. +obj = {}; +var obj2 = {}; +assertEq(Reflect.set(obj, "prop", 47, obj2), true); +assertDeepEq(obj, {}); +assertDeepEq(Reflect.getOwnPropertyDescriptor(obj2, "prop"), + {value: 47, writable: true, enumerable: true, configurable: true}); + +// If the property doesn't already exist, and the receiver isn't an object, return false. +for (var v of SOME_PRIMITIVE_VALUES) { + assertEq(Reflect.set({}, "x", 0, v), false); +} + +// Receiver defaults to the target. +obj = {}; +var hits; +var expectedReceiver; +var proxy = new Proxy(obj, { + set(t, k, v, r) { + assertEq(t, obj); + assertEq(k, "key"); + assertEq(v, "value"); + assertEq(r, expectedReceiver); // not obj + hits++; + return true; + } +}); +hits = 0; +expectedReceiver = proxy; +assertEq(Reflect.set(proxy, "key", "value"), true); +assertEq(hits, 1); + +// But not if explicitly present and undefined. +hits = 0; +expectedReceiver = undefined; +assertEq(Reflect.set(proxy, "key", "value", undefined), true); +assertEq(hits, 1); + +// Reflect.set can be used as fallback behavior in a proxy handler .set() +// method. +var log; +obj = { + set prop(v) { + log += "p"; + assertEq(v, "value"); + assertEq(this, proxy); // not obj! + } +}; +proxy = new Proxy(obj, { + set(t, k, v, r) { + assertEq(t, obj); + assertEq(r, proxy); + log += "s"; + return Reflect.set(t, k, v, r); + } +}); +log = ""; +assertEq(Reflect.set(proxy, "prop", "value"), true); +assertEq(log, "sp"); + + +// === Cross-compartment wrapper behavior. + +// When calling a cross-compartment wrapper, receiver is rewrapped for the +// target compartment. +var g = newGlobal(); +if (!("assertEq" in g)) + g.assertEq = assertEq; // necessary in the browser +g.eval(` + var hits; + var obj = { + set x(v) { + "use strict"; + assertEq(this, receiver); + assertEq(v, "xyzzy"); + hits++; + } + }; + var receiver = {}; +`); +g.hits = 0; +assertEq(Reflect.set(g.obj, "x", "xyzzy", g.receiver), true); +assertEq(g.hits, 1); + +// ...even when receiver is from a different compartment than target. +var receiver = {}; +g.receiver = receiver; +g.hits = 0; +assertEq(Reflect.set(g.obj, "x", "xyzzy", receiver), true); +assertEq(g.hits, 1); + +// ...even when receiver is a primtive value, even undefined. +for (receiver of SOME_PRIMITIVE_VALUES) { + g.receiver = receiver; + g.hits = 0; + assertEq(Reflect.set(g.obj, "x", "xyzzy", receiver), true); + assertEq(g.hits, 1); +} + + +// === Less than 3 arguments + +// With two arguments, the value is assumed to be undefined. +obj = {}; +assertEq(Reflect.set(obj, "size"), true); +assertDeepEq(Reflect.getOwnPropertyDescriptor(obj, "size"), + {value: undefined, writable: true, enumerable: true, configurable: true}); + +// With just one argument, the key is "undefined". +obj = {}; +assertEq(Reflect.set(obj), true); +assertDeepEq(Reflect.getOwnPropertyDescriptor(obj, "undefined"), + {value: undefined, writable: true, enumerable: true, configurable: true}); + +// For the no argument-case, see target.js. + + +// === Failure cases + +// Non-writable data property +obj = {}; +Reflect.defineProperty(obj, "x", {value: 0, writable: false}); +assertEq(Reflect.set(obj, "x", 1), false); +assertEq(obj.x, 0); + +// The same, but inherited from a prototype +var obj2 = Object.create(obj); +assertEq(Reflect.set(obj2, "x", 1), false); +assertEq(obj2.hasOwnProperty("x"), false); +assertEq(obj2.x, 0); + +// Getter, no setter +obj = {}; +var desc = {get: () => 12, set: undefined, enumerable: false, configurable: true}; +Reflect.defineProperty(obj, "y", desc); +assertEq(Reflect.set(obj, "y", 13), false); +assertDeepEq(Reflect.getOwnPropertyDescriptor(obj, "y"), desc); + +// The same, but inherited from a prototype +obj2 = Object.create(obj); +assertEq(Reflect.set(obj2, "y", 1), false); +assertEq(obj2.hasOwnProperty("y"), false); +assertDeepEq(Reflect.getOwnPropertyDescriptor(obj, "y"), desc); + +// Proxy set handler returns a false value +for (var no of [false, ""]) { + var hits = 0; + obj = {}; + var proxy = new Proxy(obj, { + set(t, k, v, r) { + assertEq(t, obj); + assertEq(k, "x"); + assertEq(v, 33); + assertEq(r, proxy); + hits++; + return no; + } + }); + assertEq(Reflect.set(proxy, "x", 33), false); + assertEq(hits, 1); + assertEq("x" in obj, false); +} + +// Proxy handler method throws +obj = {}; +proxy = new Proxy(obj, { + set(t, k, v, r) { throw "i don't like " + v; } +}); +assertThrowsValue(() => Reflect.set(proxy, "food", "cheese"), "i don't like cheese"); + +// If a Proxy set handler breaks the object invariants, it's a TypeError. +for (obj of [{a: 0}, {get a() { return 0; }}]) { + Object.freeze(obj); + proxy = new Proxy(obj, { + set(t, k, v, r) { return true; } + }); + assertThrowsInstanceOf(() => Reflect.set(proxy, "a", "b"), TypeError); +} + +// Per spec, this should first call p.[[Set]]("0", 42, a) and +// then (since p has no own properties) a.[[Set]]("0", 42, a). +// The latter should not define a property on p. +var a = [0, 1, 2, 3]; +var p = Object.create(a); +Reflect.set(p, "0", 42, a); +assertEq(p.hasOwnProperty("0"), false); +assertDeepEq(Reflect.getOwnPropertyDescriptor(a, "0"), + {value: 42, writable: true, enumerable: true, configurable: true}); + +// Test behavior of ordinary objects' [[Set]] method (ES6 9.1.9). +// On an ordinary object, if the property key isn't present, [[Set]] calls +// receiver.[[GetOwnProperty]]() and then receiver.[[DefineProperty]](). +var log; +obj = {}; +var proxyTarget = {}; +var existingDescriptor, expected, defineResult; +var receiver = new Proxy(proxyTarget, { + getOwnPropertyDescriptor(t, k) { + log += "g"; + return existingDescriptor; + }, + defineProperty(t, k, desc) { + log += "d"; + assertEq(t, proxyTarget); + assertEq(k, "prop"); + assertDeepEq(desc, expected); + return defineResult; + } +}); +existingDescriptor = undefined; +expected = {value: 5, writable: true, enumerable: true, configurable: true}; +for (var defineResult of [true, false]) { + log = ""; + assertEq(Reflect.set(obj, "prop", 5, receiver), defineResult); + assertEq(log, "gd"); +} + +existingDescriptor = {value: 7, writable: true, enumerable: false, configurable: true}; +expected = {value: 4}; +for (var defineResult of [true, false]) { + log = ""; + assertEq(Reflect.set(obj, "prop", 4, receiver), defineResult); + assertEq(log, "gd"); +} + + +// For more Reflect.set tests, see target.js and propertyKeys.js. + +reportCompare(0, 0); diff --git a/js/src/tests/non262/Reflect/setPrototypeOf.js b/js/src/tests/non262/Reflect/setPrototypeOf.js new file mode 100644 index 0000000000..ed7857a028 --- /dev/null +++ b/js/src/tests/non262/Reflect/setPrototypeOf.js @@ -0,0 +1,72 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Reflect.setPrototypeOf changes an object's [[Prototype]]. +var obj = {}; +assertEq(Object.getPrototypeOf(obj), Object.prototype); +var proto = {}; +assertEq(Reflect.setPrototypeOf(obj, proto), true); +assertEq(Object.getPrototypeOf(obj), proto); + +// It can change an object's [[Prototype]] to null. +obj = {}; +assertEq(Reflect.setPrototypeOf(obj, null), true); +assertEq(Object.getPrototypeOf(obj), null); + +// The proto argument is required too. +obj = {}; +assertThrowsInstanceOf(() => Reflect.setPrototypeOf(obj), TypeError); + +// The proto argument must be either null or an object. +for (proto of [undefined, false, 0, 1.6, "that", Symbol.iterator]) { + assertThrowsInstanceOf(() => Reflect.setPrototypeOf(obj, proto), TypeError); +} + +// Return false if the target isn't extensible. +proto = {}; +obj = Object.preventExtensions(Object.create(proto)); +assertEq(Reflect.setPrototypeOf(obj, {}), false); +assertEq(Reflect.setPrototypeOf(obj, null), false); +assertEq(Reflect.setPrototypeOf(obj, proto), true); // except if not changing anything + +// Return false rather than create a [[Prototype]] cycle. +obj = {}; +assertEq(Reflect.setPrototypeOf(obj, obj), false); + +// Don't create a [[Prototype]] cycle involving 2 objects. +obj = Object.create(proto); +assertEq(Reflect.setPrototypeOf(proto, obj), false); + +// Don't create a longish [[Prototype]] cycle. +for (var i = 0; i < 256; i++) + obj = Object.create(obj); +assertEq(Reflect.setPrototypeOf(proto, obj), false); + +// The spec claims we should allow creating cycles involving proxies. (The +// cycle check quietly exits on encountering the proxy.) +obj = {}; +var proxy = new Proxy(Object.create(obj), {}); + +assertEq(Reflect.setPrototypeOf(obj, proxy), true); +assertEq(Reflect.getPrototypeOf(obj), proxy); +assertEq(Reflect.getPrototypeOf(proxy), obj); + +// If a proxy handler returns a false-y value, return false. +var hits = 0; +proto = {name: "proto"}; +obj = {name: "obj"}; +proxy = new Proxy(obj, { + setPrototypeOf(t, p) { + assertEq(t, obj); + assertEq(p, proto); + hits++; + return 0; + } +}); + +assertEq(Reflect.setPrototypeOf(proxy, proto), false); +assertEq(hits, 1); + +// For more Reflect.setPrototypeOf tests, see target.js. + +reportCompare(0, 0); diff --git a/js/src/tests/non262/Reflect/shell.js b/js/src/tests/non262/Reflect/shell.js new file mode 100644 index 0000000000..2aa5397ed9 --- /dev/null +++ b/js/src/tests/non262/Reflect/shell.js @@ -0,0 +1,9 @@ +// List of a few values that are not objects. +var SOME_PRIMITIVE_VALUES = [ + undefined, null, + false, + -Infinity, -1.6e99, -1, -0, 0, Math.pow(2, -1074), 1, 4294967295, + Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER + 1, 1.6e99, Infinity, NaN, + "", "Phaedo", + Symbol(), Symbol("iterator"), Symbol.for("iterator"), Symbol.iterator +]; diff --git a/js/src/tests/non262/Reflect/surfaces.js b/js/src/tests/non262/Reflect/surfaces.js new file mode 100644 index 0000000000..f3bac51873 --- /dev/null +++ b/js/src/tests/non262/Reflect/surfaces.js @@ -0,0 +1,59 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Check surface features of the Reflect object. +assertEq(typeof Reflect, 'object'); +assertEq(Object.getPrototypeOf(Reflect), Object.prototype); +assertEq(Reflect.toString(), '[object Reflect]'); +assertThrowsInstanceOf(() => new Reflect, TypeError); + +var desc = Object.getOwnPropertyDescriptor(this, "Reflect"); +assertEq(desc.enumerable, false); +assertEq(desc.configurable, true); +assertEq(desc.writable, true); + +for (const name in Reflect) + throw new Error("Reflect should not have any enumerable properties"); + +// The name and length of all the standard Reflect methods. +var methods = { + apply: 3, + construct: 2, + defineProperty: 3, + deleteProperty: 2, + get: 2, + getOwnPropertyDescriptor: 2, + getPrototypeOf: 1, + has: 2, + isExtensible: 1, + ownKeys: 1, + preventExtensions: 1, + set: 3, + setPrototypeOf: 2 +}; + +// Check that all Reflect properties are listed above. +for (const name of Reflect.ownKeys(Reflect)) { + // If this assertion fails, congratulations on implementing a new Reflect feature! + // Add it to the list of methods above. + if (typeof name !== "symbol" && name !== "parse") + assertEq(name in methods, true, `unexpected property found: Reflect.${name}`); +} + +// Check the .length and property attributes of each Reflect method. +for (const name of Object.keys(methods)) { + var desc = Object.getOwnPropertyDescriptor(Reflect, name); + assertEq(desc.enumerable, false); + assertEq(desc.configurable, true); + assertEq(desc.writable, true); + var f = desc.value; + assertEq(typeof f, "function"); + assertEq(f.length, methods[name]); +} + +// Check that the SpiderMonkey "resolve hook" mechanism does not resurrect the +// Reflect property once it is deleted. +delete this.Reflect; +assertEq("Reflect" in this, false); + +reportCompare(0, 0); diff --git a/js/src/tests/non262/Reflect/target.js b/js/src/tests/non262/Reflect/target.js new file mode 100644 index 0000000000..f35fe816ad --- /dev/null +++ b/js/src/tests/non262/Reflect/target.js @@ -0,0 +1,44 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Check correct handling of the `target` argument shared by every Reflect method. + +// For each standard Reflect method, an array of arguments +// that would be OK after a suitable target argument. +var methodInfo = { + apply: [undefined, []], + construct: [[]], + defineProperty: ["x", {}], + deleteProperty: ["x"], + get: ["x", {}], + getOwnPropertyDescriptor: ["x"], + getPrototypeOf: [], + has: ["x"], + isExtensible: [], + ownKeys: [], + preventExtensions: [], + set: ["x", 0], + setPrototypeOf: [{}] +}; + +// Check that all Reflect properties are listed above. +for (const name of Reflect.ownKeys(Reflect)) { + // If this assertion fails, congratulations on implementing a new Reflect feature! + // Add it to methodInfo above. + if (typeof name !== "symbol" && name !== "parse") + assertEq(name in methodInfo, true); +} + +for (const name of Object.keys(methodInfo)) { + var args = methodInfo[name]; + + // The target argument is required. + assertThrowsInstanceOf(Reflect[name], TypeError); + + // Throw if the target argument is not an object. + for (var value of SOME_PRIMITIVE_VALUES) { + assertThrowsInstanceOf(() => Reflect[name](value, ...args), TypeError); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/non262/RegExp/15.10.5-01.js b/js/src/tests/non262/RegExp/15.10.5-01.js new file mode 100644 index 0000000000..2f8429218a --- /dev/null +++ b/js/src/tests/non262/RegExp/15.10.5-01.js @@ -0,0 +1,21 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 614603; +var summary = "RegExp.length"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +assertEq(RegExp.length, 2); +assertEq(/a/.constructor.length, 2); + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/RegExp/15.10.6.2-2.js b/js/src/tests/non262/RegExp/15.10.6.2-2.js new file mode 100644 index 0000000000..3dfb6ac74f --- /dev/null +++ b/js/src/tests/non262/RegExp/15.10.6.2-2.js @@ -0,0 +1,292 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * + * Date: 18 Feb 2002 + * SUMMARY: Testing re.exec(str) when re.lastIndex is < 0 or > str.length + * + * Case 1: If re has the global flag set, then re(str) should be null + * Case 2: If re doesn't have this set, then re(str) should be unaffected + * + * See http://bugzilla.mozilla.org/show_bug.cgi?id=76717 + * + * + * From the ECMA-262 Final spec: + * + * 15.10.6.2 RegExp.prototype.exec(string) + * Performs a regular expression match of string against the regular + * expression and returns an Array object containing the results of + * the match, or null if the string did not match. + * + * The string ToString(string) is searched for an occurrence of the + * regular expression pattern as follows: + * + * 1. Let S be the value of ToString(string). + * 2. Let length be the length of S. + * 3. Let lastIndex be the value of the lastIndex property. + * 4. Let i be the value of ToInteger(lastIndex). + * 5. If the global property is false, let i = 0. + * 6. If i < 0 or i > length then set lastIndex to 0 and return null. + * 7. Call [[Match]], giving it the arguments S and i. + * If [[Match]] returned failure, go to step 8; + * otherwise let r be its State result and go to step 10. + * 8. Let i = i+1. + * 9. Go to step 6. + * 10. Let e be r's endIndex value. + * 11. If the global property is true, set lastIndex to e. + * + * etc. + * + * + * So: + * + * A. If the global flag is not set, |lastIndex| is set to 0 + * before the match is attempted; thus the match is unaffected. + * + * B. If the global flag IS set and re.lastIndex is >= 0 and <= str.length, + * |lastIndex| is incremented every time there is a match; not from + * i to i+1, but from i to "endIndex" e: + * + * e = (index of last input character matched so far by the pattern) + 1 + * + * The match is then attempted from this position in the string (Step 7). + * + * C. When the global flag IS set and re.lastIndex is < 0 or > str.length, + * |lastIndex| is set to 0 and the match returns null. + * + * + * Note the |lastIndex| property is writeable, and may be set arbitrarily + * by the programmer - and we will do that below. + * + */ +//----------------------------------------------------------------------------- +var i = 0; +var BUGNUMBER = 76717; +var summary = 'Testing re.exec(str) when re.lastIndex is < 0 or > str.length'; +var status = ''; +var statusmessages = new Array(); +var pattern = ''; +var patterns = new Array(); +var string = ''; +var strings = new Array(); +var actualmatch = ''; +var actualmatches = new Array(); +var expectedmatch = ''; +var expectedmatches = new Array(); + + +/****************************************************************************** + * + * Case 1 : when the global flag is set - + * + *****************************************************************************/ +pattern = /abc/gi; +string = 'AbcaBcabC'; + +status = inSection(1); +actualmatch = pattern.exec(string); +expectedmatch = Array('Abc'); +addThis(); + +status = inSection(2); +actualmatch = pattern.exec(string); +expectedmatch = Array('aBc'); +addThis(); + +status = inSection(3); +actualmatch = pattern.exec(string); +expectedmatch = Array('abC'); +addThis(); + +/* + * At this point |lastIndex| is > string.length, so the match should be null - + */ +status = inSection(4); +actualmatch = pattern.exec(string); +expectedmatch = null; +addThis(); + +/* + * Now try some edge-case values. Thanks to the work done in + * http://bugzilla.mozilla.org/show_bug.cgi?id=124339, |lastIndex| + * is now stored as a double instead of a uint32_t (unsigned integer). + * + * Note 2^32 -1 is the upper bound for uint32's, but doubles can go + * all the way up to Number.MAX_VALUE. So that's why we need cases + * between those two numbers. + */ +status = inSection(6); +pattern.lastIndex = Math.pow(2,32); +actualmatch = pattern.exec(string); +expectedmatch = null; +addThis(); + +status = inSection(8); +pattern.lastIndex = Math.pow(2,32) + 1; +actualmatch = pattern.exec(string); +expectedmatch = null; +addThis(); + +status = inSection(10); +pattern.lastIndex = Math.pow(2,32) * 2; +actualmatch = pattern.exec(string); +expectedmatch = null; +addThis(); + +status = inSection(12); +pattern.lastIndex = Math.pow(2,40); +actualmatch = pattern.exec(string); +expectedmatch = null; +addThis(); + +status = inSection(14); +pattern.lastIndex = Number.MAX_VALUE; +actualmatch = pattern.exec(string); +expectedmatch = null; +addThis(); + + + +/****************************************************************************** + * + * Case 2: repeat all the above cases WITHOUT the global flag set. + * According to EMCA. |lastIndex| should get set to 0 before the match. + * + * Therefore re.exec(str) should be unaffected; thus our expected values + * below are now DIFFERENT when |lastIndex| is < 0 or > str.length + * + *****************************************************************************/ + +pattern = /abc/i; +string = 'AbcaBcabC'; + +status = inSection(16); +actualmatch = pattern.exec(string); +expectedmatch = Array('Abc'); +addThis(); + +status = inSection(17); +actualmatch = pattern.exec(string); +expectedmatch = Array('Abc'); // NOT Array('aBc') as before - +addThis(); + +status = inSection(18); +actualmatch = pattern.exec(string); +expectedmatch = Array('Abc'); // NOT Array('abC') as before - +addThis(); + +/* + * At this point above, |lastIndex| WAS > string.length, but not here - + */ +status = inSection(19); +actualmatch = pattern.exec(string); +expectedmatch = Array('Abc') // NOT null as before - + addThis(); + +/* + * Now let's set |lastIndex| to -1 + */ +status = inSection(20); +pattern.lastIndex = -1; +actualmatch = pattern.exec(string); +expectedmatch = Array('Abc') // NOT null as before - + addThis(); + +/* + * Now try some edge-case values. Thanks to the work done in + * http://bugzilla.mozilla.org/show_bug.cgi?id=124339, |lastIndex| + * is now stored as a double instead of a uint32_t (unsigned integer). + * + * Note 2^32 -1 is the upper bound for uint32's, but doubles can go + * all the way up to Number.MAX_VALUE. So that's why we need cases + * between those two numbers. + */ +status = inSection(21); +pattern.lastIndex = Math.pow(2,32); +actualmatch = pattern.exec(string); +expectedmatch = Array('Abc') // NOT null as before - + addThis(); + +status = inSection(22); +pattern.lastIndex = -Math.pow(2,32); +actualmatch = pattern.exec(string); +expectedmatch = Array('Abc') // NOT null as before - + addThis(); + +status = inSection(23); +pattern.lastIndex = Math.pow(2,32) + 1; +actualmatch = pattern.exec(string); +expectedmatch = Array('Abc') // NOT null as before - + addThis(); + +status = inSection(24); +pattern.lastIndex = -(Math.pow(2,32) + 1); +actualmatch = pattern.exec(string); +expectedmatch = Array('Abc') // NOT null as before - + addThis(); + +status = inSection(25); +pattern.lastIndex = Math.pow(2,32) * 2; +actualmatch = pattern.exec(string); +expectedmatch = Array('Abc') // NOT null as before - + addThis(); + +status = inSection(26); +pattern.lastIndex = -Math.pow(2,32) * 2; +actualmatch = pattern.exec(string); +expectedmatch = Array('Abc') // NOT null as before - + addThis(); + +status = inSection(27); +pattern.lastIndex = Math.pow(2,40); +actualmatch = pattern.exec(string); +expectedmatch = Array('Abc') // NOT null as before -; + addThis(); + +status = inSection(28); +pattern.lastIndex = -Math.pow(2,40); +actualmatch = pattern.exec(string); +expectedmatch = Array('Abc') // NOT null as before - + addThis(); + +status = inSection(29); +pattern.lastIndex = Number.MAX_VALUE; +actualmatch = pattern.exec(string); +expectedmatch = Array('Abc') // NOT null as before - + addThis(); + +status = inSection(30); +pattern.lastIndex = -Number.MAX_VALUE; +actualmatch = pattern.exec(string); +expectedmatch = Array('Abc') // NOT null as before - + addThis(); + + + + +//------------------------------------------------------------------------------------------------- +test(); +//------------------------------------------------------------------------------------------------- + + + +function addThis() +{ + statusmessages[i] = status; + patterns[i] = pattern; + strings[i] = string; + actualmatches[i] = actualmatch; + expectedmatches[i] = expectedmatch; + i++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + testRegExp(statusmessages, patterns, strings, actualmatches, expectedmatches); +} diff --git a/js/src/tests/non262/RegExp/15.10.7.5-01.js b/js/src/tests/non262/RegExp/15.10.7.5-01.js new file mode 100644 index 0000000000..ab9d071a7e --- /dev/null +++ b/js/src/tests/non262/RegExp/15.10.7.5-01.js @@ -0,0 +1,71 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 465199; +var summary = "RegExp lastIndex property set should not coerce type to number"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var called = false; +var o = { valueOf: function() { called = true; return 1; } }; +var r = /a/g; +var desc, m; + +assertEq(r.lastIndex, 0); + +desc = Object.getOwnPropertyDescriptor(r, "lastIndex"); +assertEq(desc.enumerable, false); +assertEq(desc.configurable, false); +assertEq(desc.value, 0); +assertEq(desc.writable, true); + +r.lastIndex = o; + +assertEq(r.lastIndex, o); + +desc = Object.getOwnPropertyDescriptor(r, "lastIndex"); +assertEq(desc.enumerable, false); +assertEq(desc.configurable, false); +assertEq(desc.value, o); +assertEq(desc.writable, true); + +assertEq(called, false); +assertEq(r.exec("aaaa").length, 1); +assertEq(called, true); +assertEq(r.lastIndex, 2); + +desc = Object.getOwnPropertyDescriptor(r, "lastIndex"); +assertEq(desc.enumerable, false); +assertEq(desc.configurable, false); +assertEq(desc.value, 2); +assertEq(desc.writable, true); + + +r.lastIndex = -0.2; +assertEq(r.lastIndex, -0.2); + +m = r.exec("aaaa"); +assertEq(Array.isArray(m), true); +assertEq(m.length, 1); +assertEq(m[0], "a"); +assertEq(r.lastIndex, 1); + +m = r.exec("aaaa"); +assertEq(Array.isArray(m), true); +assertEq(m.length, 1); +assertEq(m[0], "a"); +assertEq(r.lastIndex, 2); + + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/RegExp/15.5.4.11.js b/js/src/tests/non262/RegExp/15.5.4.11.js new file mode 100644 index 0000000000..a5515286a0 --- /dev/null +++ b/js/src/tests/non262/RegExp/15.5.4.11.js @@ -0,0 +1,498 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var BUGNUMBER = 392378; +var summary = '15.5.4.11 - String.prototype.replace'; +var rex, f, a, i; + +reportCompare( + 2, + String.prototype.replace.length, + "Section 1" +); + +reportCompare( + "321", + String.prototype.replace.call(123, "123", "321"), + "Section 2" +); + +reportCompare( + "ok", + "ok".replace(), + "Section 3" +); + +reportCompare( + "undefined**", + "***".replace("*"), + "Section 4" +); + +reportCompare( + "xnullz", + "xyz".replace("y", null), + "Section 5" +); + +reportCompare( + "x123", + "xyz".replace("yz", 123), + "Section 6" +); + +reportCompare( + "/x/g/x/g/x/g", + "xxx".replace(/x/g, /x/g), + "Section 7" +); + +reportCompare( + "ok", + "undefined".replace(undefined, "ok"), + "Section 8" +); + +reportCompare( + "ok", + "null".replace(null, "ok"), + "Section 9" +); + +reportCompare( + "ok", + "123".replace(123, "ok"), + "Section 10" +); + +reportCompare( + "xzyxyz", + "xyzxyz".replace("yz", "zy"), + "Section 11" +); + +reportCompare( + "ok", + "(xyz)".replace("(xyz)", "ok"), + "Section 12" +); + +reportCompare( + "*$&yzxyz", + "xyzxyz".replace("x", "*$$&"), + "Section 13" +); + +reportCompare( + "xy*z*", + "xyz".replace("z", "*$&*"), + "Section 14" +); + +reportCompare( + "xyxyzxyz", + "xyzxyzxyz".replace("zxy", "$`"), + "Section 15" +); + +reportCompare( + "zxyzxyzzxyz", + "xyzxyz".replace("xy", "$'xyz"), + "Section 16" +); + +reportCompare( + "$", + "xyzxyz".replace("xyzxyz", "$"), + "Section 17" +); + +reportCompare( + "x$0$00xyz", + "xyzxyz".replace("yz", "$0$00"), + "Section 18" +); + +// Result for $1/$01 .. $99 is implementation-defined if searchValue is no +// regular expression. $+ is a non-standard Mozilla extension. + +reportCompare( + "$!$\"$-1$*$#$.$xyz$$", + "xyzxyz$$".replace("xyz", "$!$\"$-1$*$#$.$"), + "Section 19" +); + +reportCompare( + "$$$&$$$&$&", + "$$$&".replace("$$", "$$$$$$&$&$$&"), + "Section 20" +); + +reportCompare( + "yxx", + "xxx".replace(/x/, "y"), + "Section 21" +); + +reportCompare( + "yyy", + "xxx".replace(/x/g, "y"), + "Section 22" +); + +rex = /x/, rex.lastIndex = 1; +reportCompare( + "yxx1", + "xxx".replace(rex, "y") + rex.lastIndex, + "Section 23" +); + +rex = /x/g, rex.lastIndex = 1; +reportCompare( + "yyy0", + "xxx".replace(rex, "y") + rex.lastIndex, + "Section 24" +); + +rex = /y/, rex.lastIndex = 1; +reportCompare( + "xxx1", + "xxx".replace(rex, "y") + rex.lastIndex, + "Section 25" +); + +rex = /y/g, rex.lastIndex = 1; +reportCompare( + "xxx0", + "xxx".replace(rex, "y") + rex.lastIndex, + "Section 26" +); + +rex = /x?/, rex.lastIndex = 1; +reportCompare( + "(x)xx1", + "xxx".replace(rex, "($&)") + rex.lastIndex, + "Section 27" +); + +rex = /x?/g, rex.lastIndex = 1; +reportCompare( + "(x)(x)(x)()0", + "xxx".replace(rex, "($&)") + rex.lastIndex, + "Section 28" +); + +rex = /y?/, rex.lastIndex = 1; +reportCompare( + "()xxx1", + "xxx".replace(rex, "($&)") + rex.lastIndex, + "Section 29" +); + +rex = /y?/g, rex.lastIndex = 1; +reportCompare( + "()x()x()x()0", + "xxx".replace(rex, "($&)") + rex.lastIndex, + "Section 30" +); + +reportCompare( + "xy$0xy$zxy$zxyz$zxyz", + "xyzxyzxyz".replace(/zxy/, "$0$`$$$&$$$'$"), + "Section 31" +); + +reportCompare( + "xy$0xy$zxy$zxyz$$0xyzxy$zxy$z$z", + "xyzxyzxyz".replace(/zxy/g, "$0$`$$$&$$$'$"), + "Section 32" +); + +reportCompare( + "xyxyxyzxyxyxyz", + "xyzxyz".replace(/(((x)(y)()()))()()()(z)/g, "$01$2$3$04$5$6$7$8$09$10"), + "Section 33" +); + +rex = RegExp( + "()()()()()()()()()()" + + "()()()()()()()()()()" + + "()()()()()()()()()()" + + "()()()()()()()()()()" + + "()()()()()()()()()()" + + "()()()()()()()()()()" + + "()()()()()()()()()()" + + "()()()()()()()()()()" + + "()()()()()()()()()()" + + "()()()()()()()()(y)"); +reportCompare( + "x(y)z", + "xyz".replace(rex, "($99)"), + "Section 34" +); + +rex = RegExp( + "()()()()()()()()()(x)" + + "()()()()()()()()()()" + + "()()()()()()()()()()" + + "()()()()()()()()()()" + + "()()()()()()()()()()" + + "()()()()()()()()()()" + + "()()()()()()()()()()" + + "()()()()()()()()()()" + + "()()()()()()()()()()" + + "()()()()()()()()()(y)"); +reportCompare( + "(x0)z", + "xyz".replace(rex, "($100)"), + "Section 35" +); + +reportCompare( + "xyz(XYZ)", + "xyzXYZ".replace(/XYZ/g, "($&)"), + "Section 36" +); + +reportCompare( + "(xyz)(XYZ)", + "xyzXYZ".replace(/xYz/gi, "($&)"), + "Section 37" +); + +reportCompare( + "xyz\rxyz\n", + "xyz\rxyz\n".replace(/xyz$/g, "($&)"), + "Section 38" +); + +reportCompare( + "(xyz)\r(xyz)\n", + "xyz\rxyz\n".replace(/xyz$/gm, "($&)"), + "Section 39" +); + +f = function () { return "failure" }; + +reportCompare( + "ok", + "ok".replace("x", f), + "Section 40" +); + +reportCompare( + "ok", + "ok".replace(/(?=k)ok/, f), + "Section 41" +); + +reportCompare( + "ok", + "ok".replace(/(?!)ok/, f), + "Section 42" +); + +reportCompare( + "ok", + "ok".replace(/ok(?!$)/, f), + "Section 43" +); + +f = function (sub, offs, str) { + return ["", sub, typeof sub, offs, typeof offs, str, typeof str, ""] + .join("|"); +}; + +reportCompare( + "x|y|string|1|number|xyz|string|z", + "xyz".replace("y", f), + "Section 44" +); + +reportCompare( + "x|(y)|string|1|number|x(y)z|string|z", + "x(y)z".replace("(y)", f), + "Section 45" +); + +reportCompare( + "x|y*|string|1|number|xy*z|string|z", + "xy*z".replace("y*", f), + "Section 46" +); + +reportCompare( + "12|3|string|2|number|12345|string|45", + String.prototype.replace.call(1.2345e4, 3, f), + "Section 47" +); + +reportCompare( + "|x|string|0|number|xxx|string|xx", + "xxx".replace(/^x/g, f), + "Section 48" +); + +reportCompare( + "xx|x|string|2|number|xxx|string|", + "xxx".replace(/x$/g, f), + "Section 49" +); + +f = function (sub, paren, offs, str) { + return ["", sub, typeof sub, paren, typeof paren, offs, typeof offs, + str, typeof str, ""].join("|"); +}; + +reportCompare( + "xy|z|string|z|string|2|number|xyz|string|", + "xyz".replace(/(z)/g, f), + "Section 50" +); + +reportCompare( + "xyz||string||string|3|number|xyz|string|", + "xyz".replace(/($)/g, f), + "Section 51" +); + +reportCompare( + "|xy|string|y|string|0|number|xyz|string|z", + "xyz".replace(/(?:x)(y)/g, f), + "Section 52" +); + +reportCompare( + "|x|string|x|string|0|number|xyz|string|yz", + "xyz".replace(/((?=xy)x)/g, f), + "Section 53" +); + +reportCompare( + "|x|string|x|string|0|number|xyz|string|yz", + "xyz".replace(/(x(?=y))/g, f), + "Section 54" +); + +reportCompare( + "x|y|string|y|string|1|number|xyz|string|z", + "xyz".replace(/((?!x)y)/g, f), + "Section 55" +); + +reportCompare( + "|x|string|x|string|0|number|xyz|string|" + + "|y|string||undefined|1|number|xyz|string|z", + "xyz".replace(/y|(x)/g, f), + "Section 56" +); + +reportCompare( + "xy|z|string||string|2|number|xyz|string|", + "xyz".replace(/(z?)z/, f), + "Section 57" +); + +reportCompare( + "xy|z|string||undefined|2|number|xyz|string|", + "xyz".replace(/(z)?z/, f), + "Section 58" +); + +reportCompare( + "xy|z|string||undefined|2|number|xyz|string|", + "xyz".replace(/(z)?\1z/, f), + "Section 59" +); + +reportCompare( + "xy|z|string||undefined|2|number|xyz|string|", + "xyz".replace(/\1(z)?z/, f), + "Section 60" +); + +reportCompare( + "xy|z|string||string|2|number|xyz|string|", + "xyz".replace(/(z?\1)z/, f), + "Section 61" +); + +f = function (sub, paren1, paren2, offs, str) { + return ["", sub, typeof sub, paren1, typeof paren1, paren2, typeof paren2, + offs, typeof offs, str, typeof str, ""].join("|"); +}; + +reportCompare( + "x|y|string|y|string||undefined|1|number|xyz|string|z", + "xyz".replace(/(y)(\1)?/, f), + "Section 62" +); + +reportCompare( + "x|yy|string|y|string|y|string|1|number|xyyz|string|z", + "xyyz".replace(/(y)(\1)?/g, f), + "Section 63" +); + +reportCompare( + "x|y|string|y|string||undefined|1|number|xyyz|string|" + + "|y|string|y|string||undefined|2|number|xyyz|string|z", + "xyyz".replace(/(y)(\1)??/g, f), + "Section 64" +); + +reportCompare( + "x|y|string|y|string|y|string|1|number|xyz|string|z", + "xyz".replace(/(?=(y))(\1)?/, f), + "Section 65" +); + +reportCompare( + "xyy|z|string||undefined||string|3|number|xyyz|string|", + "xyyz".replace(/(?!(y)y)(\1)z/, f), + "Section 66" +); + +rex = RegExp( + "()()()()()()()()()()" + + "()()()()()()()()()()" + + "()()()()()()()()()()" + + "()()()()()()()()()()" + + "()()()()()()()()()()" + + "()()()()()()()()()()" + + "()()()()()()()()()()" + + "()()()()()()()()()()" + + "()()()()()()()()()()" + + "()()()()()()()()()()(z)?(y)"); +a = ["sub"]; +for (i = 1; i <= 102; ++i) + a[i] = "p" + i; +a[103] = "offs"; +a[104] = "str"; +a[105] = "return ['', sub, typeof sub, offs, typeof offs, str, typeof str, " + + "p100, typeof p100, p101, typeof p101, p102, typeof p102, ''].join('|');"; +f = Function.apply(null, a); +reportCompare( + "x|y|string|1|number|xyz|string||string||undefined|y|string|z", + "xyz".replace(rex, f), + "Section 67" +); + +reportCompare( + "undefined", + "".replace(/.*/g, function () {}), + "Section 68" +); + +reportCompare( + "nullxnullynullznull", + "xyz".replace(/.??/g, function () { return null; }), + "Section 69" +); + +reportCompare( + "111", + "xyz".replace(/./g, function () { return 1; }), + "Section 70" +); diff --git a/js/src/tests/non262/RegExp/7.8.5-01.js b/js/src/tests/non262/RegExp/7.8.5-01.js new file mode 100644 index 0000000000..be09bbc142 --- /dev/null +++ b/js/src/tests/non262/RegExp/7.8.5-01.js @@ -0,0 +1,35 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 615070; +var summary = "Line terminator after backslash is invalid in regexp literals"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var regexps = ["/\\\u000A/", "/\\\u000D/", "/\\\u2028/", "/\\\u2029/", + "/ab\\\n/", "/ab\\\r/", "/ab\\\u2028/", "/ab\\\u2029/", + "/ab[c\\\n]/", "/a[bc\\", "/\\"]; + +for(var i=0; i RegExp.prototype[Symbol.match].call({ exec }, "foo"), + TypeError); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/RegExpExec-return.js b/js/src/tests/non262/RegExp/RegExpExec-return.js new file mode 100644 index 0000000000..1148aac07f --- /dev/null +++ b/js/src/tests/non262/RegExp/RegExpExec-return.js @@ -0,0 +1,31 @@ +var BUGNUMBER = 887016; +var summary = "RegExpExec should throw if returned value is not an object nor null."; + +print(BUGNUMBER + ": " + summary); + +for (var ret of [null, {}, [], /a/]) { + assertEq(RegExp.prototype[Symbol.match].call({ + get global() { + return false; + }, + exec(S) { + return ret; + } + }, "foo"), ret); +} + +for (ret of [undefined, 1, true, false, Symbol.iterator]) { + assertThrowsInstanceOf(() => { + RegExp.prototype[Symbol.match].call({ + get global() { + return false; + }, + exec(S) { + return ret; + } + }, "foo"); + }, TypeError); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/RegExp_dollar_number.js b/js/src/tests/non262/RegExp/RegExp_dollar_number.js new file mode 100644 index 0000000000..52680a1870 --- /dev/null +++ b/js/src/tests/non262/RegExp/RegExp_dollar_number.js @@ -0,0 +1,76 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + Filename: RegExp_dollar_number.js + Description: 'Tests RegExps $1, ..., $9 properties' + + Author: Nick Lerissa + Date: March 12, 1998 +*/ + +var SECTION = 'As described in Netscape doc "What\'s new in JavaScript 1.2"'; +var TITLE = 'RegExp: $1, ..., $9'; +var BUGNUMBER="123802"; + +printBugNumber(BUGNUMBER); +writeHeaderToLog('Executing script: RegExp_dollar_number.js'); +writeHeaderToLog( SECTION + " "+ TITLE); + + +// 'abcdefghi'.match(/(a(b(c(d(e)f)g)h)i)/); RegExp.$1 +'abcdefghi'.match(/(a(b(c(d(e)f)g)h)i)/); +new TestCase ( "'abcdefghi'.match(/(a(b(c(d(e)f)g)h)i)/); RegExp.$1", + 'abcdefghi', RegExp.$1); + +// 'abcdefghi'.match(/(a(b(c(d(e)f)g)h)i)/); RegExp.$2 +new TestCase ( "'abcdefghi'.match(/(a(b(c(d(e)f)g)h)i)/); RegExp.$2", + 'bcdefgh', RegExp.$2); + +// 'abcdefghi'.match(/(a(b(c(d(e)f)g)h)i)/); RegExp.$3 +new TestCase ( "'abcdefghi'.match(/(a(b(c(d(e)f)g)h)i)/); RegExp.$3", + 'cdefg', RegExp.$3); + +// 'abcdefghi'.match(/(a(b(c(d(e)f)g)h)i)/); RegExp.$4 +new TestCase ( "'abcdefghi'.match(/(a(b(c(d(e)f)g)h)i)/); RegExp.$4", + 'def', RegExp.$4); + +// 'abcdefghi'.match(/(a(b(c(d(e)f)g)h)i)/); RegExp.$5 +new TestCase ( "'abcdefghi'.match(/(a(b(c(d(e)f)g)h)i)/); RegExp.$5", + 'e', RegExp.$5); + +// 'abcdefghi'.match(/(a(b(c(d(e)f)g)h)i)/); RegExp.$6 +new TestCase ( "'abcdefghi'.match(/(a(b(c(d(e)f)g)h)i)/); RegExp.$6", + '', RegExp.$6); + +var a_to_z = 'abcdefghijklmnopqrstuvwxyz'; +var regexp1 = /(a)b(c)d(e)f(g)h(i)j(k)l(m)n(o)p(q)r(s)t(u)v(w)x(y)z/ + // 'abcdefghijklmnopqrstuvwxyz'.match(/(a)b(c)d(e)f(g)h(i)j(k)l(m)n(o)p(q)r(s)t(u)v(w)x(y)z/); RegExp.$1 + a_to_z.match(regexp1); + +new TestCase ( "'" + a_to_z + "'.match((a)b(c)....(y)z); RegExp.$1", + 'a', RegExp.$1); +new TestCase ( "'" + a_to_z + "'.match((a)b(c)....(y)z); RegExp.$2", + 'c', RegExp.$2); +new TestCase ( "'" + a_to_z + "'.match((a)b(c)....(y)z); RegExp.$3", + 'e', RegExp.$3); +new TestCase ( "'" + a_to_z + "'.match((a)b(c)....(y)z); RegExp.$4", + 'g', RegExp.$4); +new TestCase ( "'" + a_to_z + "'.match((a)b(c)....(y)z); RegExp.$5", + 'i', RegExp.$5); +new TestCase ( "'" + a_to_z + "'.match((a)b(c)....(y)z); RegExp.$6", + 'k', RegExp.$6); +new TestCase ( "'" + a_to_z + "'.match((a)b(c)....(y)z); RegExp.$7", + 'm', RegExp.$7); +new TestCase ( "'" + a_to_z + "'.match((a)b(c)....(y)z); RegExp.$8", + 'o', RegExp.$8); +new TestCase ( "'" + a_to_z + "'.match((a)b(c)....(y)z); RegExp.$9", + 'q', RegExp.$9); +/* + new TestCase ( "'" + a_to_z + "'.match((a)b(c)....(y)z); RegExp.$10", + 's', RegExp.$10); +*/ +test(); diff --git a/js/src/tests/non262/RegExp/RegExp_lastMatch.js b/js/src/tests/non262/RegExp/RegExp_lastMatch.js new file mode 100644 index 0000000000..b3a02bd4d4 --- /dev/null +++ b/js/src/tests/non262/RegExp/RegExp_lastMatch.js @@ -0,0 +1,52 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + Filename: RegExp_lastMatch.js + Description: 'Tests RegExps lastMatch property' + + Author: Nick Lerissa + Date: March 12, 1998 +*/ + +var SECTION = 'As described in Netscape doc "Whats new in JavaScript 1.2"'; +var TITLE = 'RegExp: lastMatch'; + +writeHeaderToLog('Executing script: RegExp_lastMatch.js'); +writeHeaderToLog( SECTION + " "+ TITLE); + + +// 'foo'.match(/foo/); RegExp.lastMatch +'foo'.match(/foo/); +new TestCase ( "'foo'.match(/foo/); RegExp.lastMatch", + 'foo', RegExp.lastMatch); + +// 'foo'.match(new RegExp('foo')); RegExp.lastMatch +'foo'.match(new RegExp('foo')); +new TestCase ( "'foo'.match(new RegExp('foo')); RegExp.lastMatch", + 'foo', RegExp.lastMatch); + +// 'xxx'.match(/bar/); RegExp.lastMatch +'xxx'.match(/bar/); +new TestCase ( "'xxx'.match(/bar/); RegExp.lastMatch", + 'foo', RegExp.lastMatch); + +// 'xxx'.match(/$/); RegExp.lastMatch +'xxx'.match(/$/); +new TestCase ( "'xxx'.match(/$/); RegExp.lastMatch", + '', RegExp.lastMatch); + +// 'abcdefg'.match(/^..(cd)[a-z]+/); RegExp.lastMatch +'abcdefg'.match(/^..(cd)[a-z]+/); +new TestCase ( "'abcdefg'.match(/^..(cd)[a-z]+/); RegExp.lastMatch", + 'abcdefg', RegExp.lastMatch); + +// 'abcdefgabcdefg'.match(/(a(b(c(d)e)f)g)\1/); RegExp.lastMatch +'abcdefgabcdefg'.match(/(a(b(c(d)e)f)g)\1/); +new TestCase ( "'abcdefgabcdefg'.match(/(a(b(c(d)e)f)g)\\1/); RegExp.lastMatch", + 'abcdefgabcdefg', RegExp.lastMatch); + +test(); diff --git a/js/src/tests/non262/RegExp/RegExp_lastMatch_as_array.js b/js/src/tests/non262/RegExp/RegExp_lastMatch_as_array.js new file mode 100644 index 0000000000..7356bd0464 --- /dev/null +++ b/js/src/tests/non262/RegExp/RegExp_lastMatch_as_array.js @@ -0,0 +1,52 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + Filename: RegExp_lastMatch_as_array.js + Description: 'Tests RegExps $& property (same tests as RegExp_lastMatch.js but using $&)' + + Author: Nick Lerissa + Date: March 13, 1998 +*/ + +var SECTION = 'As described in Netscape doc "Whats new in JavaScript 1.2"'; +var TITLE = 'RegExp: $&'; + +writeHeaderToLog('Executing script: RegExp_lastMatch_as_array.js'); +writeHeaderToLog( SECTION + " "+ TITLE); + + +// 'foo'.match(/foo/); RegExp['$&'] +'foo'.match(/foo/); +new TestCase ( "'foo'.match(/foo/); RegExp['$&']", + 'foo', RegExp['$&']); + +// 'foo'.match(new RegExp('foo')); RegExp['$&'] +'foo'.match(new RegExp('foo')); +new TestCase ( "'foo'.match(new RegExp('foo')); RegExp['$&']", + 'foo', RegExp['$&']); + +// 'xxx'.match(/bar/); RegExp['$&'] +'xxx'.match(/bar/); +new TestCase ( "'xxx'.match(/bar/); RegExp['$&']", + 'foo', RegExp['$&']); + +// 'xxx'.match(/$/); RegExp['$&'] +'xxx'.match(/$/); +new TestCase ( "'xxx'.match(/$/); RegExp['$&']", + '', RegExp['$&']); + +// 'abcdefg'.match(/^..(cd)[a-z]+/); RegExp['$&'] +'abcdefg'.match(/^..(cd)[a-z]+/); +new TestCase ( "'abcdefg'.match(/^..(cd)[a-z]+/); RegExp['$&']", + 'abcdefg', RegExp['$&']); + +// 'abcdefgabcdefg'.match(/(a(b(c(d)e)f)g)\1/); RegExp['$&'] +'abcdefgabcdefg'.match(/(a(b(c(d)e)f)g)\1/); +new TestCase ( "'abcdefgabcdefg'.match(/(a(b(c(d)e)f)g)\\1/); RegExp['$&']", + 'abcdefgabcdefg', RegExp['$&']); + +test(); diff --git a/js/src/tests/non262/RegExp/RegExp_lastParen.js b/js/src/tests/non262/RegExp/RegExp_lastParen.js new file mode 100644 index 0000000000..06f9d6c524 --- /dev/null +++ b/js/src/tests/non262/RegExp/RegExp_lastParen.js @@ -0,0 +1,66 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + Filename: RegExp_lastParen.js + Description: 'Tests RegExps lastParen property' + + Author: Nick Lerissa + Date: March 12, 1998 +*/ + +var SECTION = 'As described in Netscape doc "Whats new in JavaScript 1.2"'; +var TITLE = 'RegExp: lastParen'; + +writeHeaderToLog('Executing script: RegExp_lastParen.js'); +writeHeaderToLog( SECTION + " "+ TITLE); + +// 'abcd'.match(/(abc)d/); RegExp.lastParen +'abcd'.match(/(abc)d/); +new TestCase ( "'abcd'.match(/(abc)d/); RegExp.lastParen", + 'abc', RegExp.lastParen); + +// 'abcd'.match(new RegExp('(abc)d')); RegExp.lastParen +'abcd'.match(new RegExp('(abc)d')); +new TestCase ( "'abcd'.match(new RegExp('(abc)d')); RegExp.lastParen", + 'abc', RegExp.lastParen); + +// 'abcd'.match(/(bcd)e/); RegExp.lastParen +'abcd'.match(/(bcd)e/); +new TestCase ( "'abcd'.match(/(bcd)e/); RegExp.lastParen", + 'abc', RegExp.lastParen); + +// 'abcdefg'.match(/(a(b(c(d)e)f)g)/); RegExp.lastParen +'abcdefg'.match(/(a(b(c(d)e)f)g)/); +new TestCase ( "'abcdefg'.match(/(a(b(c(d)e)f)g)/); RegExp.lastParen", + 'd', RegExp.lastParen); + +// 'abcdefg'.match(/(a(b)c)(d(e)f)/); RegExp.lastParen +'abcdefg'.match(/(a(b)c)(d(e)f)/); +new TestCase ( "'abcdefg'.match(/(a(b)c)(d(e)f)/); RegExp.lastParen", + 'e', RegExp.lastParen); + +// 'abcdefg'.match(/(^)abc/); RegExp.lastParen +'abcdefg'.match(/(^)abc/); +new TestCase ( "'abcdefg'.match(/(^)abc/); RegExp.lastParen", + '', RegExp.lastParen); + +// 'abcdefg'.match(/(^a)bc/); RegExp.lastParen +'abcdefg'.match(/(^a)bc/); +new TestCase ( "'abcdefg'.match(/(^a)bc/); RegExp.lastParen", + 'a', RegExp.lastParen); + +// 'abcdefg'.match(new RegExp('(^a)bc')); RegExp.lastParen +'abcdefg'.match(new RegExp('(^a)bc')); +new TestCase ( "'abcdefg'.match(new RegExp('(^a)bc')); RegExp.lastParen", + 'a', RegExp.lastParen); + +// 'abcdefg'.match(/bc/); RegExp.lastParen +'abcdefg'.match(/bc/); +new TestCase ( "'abcdefg'.match(/bc/); RegExp.lastParen", + '', RegExp.lastParen); + +test(); diff --git a/js/src/tests/non262/RegExp/RegExp_lastParen_as_array.js b/js/src/tests/non262/RegExp/RegExp_lastParen_as_array.js new file mode 100644 index 0000000000..4a5663ab67 --- /dev/null +++ b/js/src/tests/non262/RegExp/RegExp_lastParen_as_array.js @@ -0,0 +1,66 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + Filename: RegExp_lastParen_as_array.js + Description: 'Tests RegExps $+ property (same tests as RegExp_lastParen.js but using $+)' + + Author: Nick Lerissa + Date: March 13, 1998 +*/ + +var SECTION = 'As described in Netscape doc "Whats new in JavaScript 1.2"'; +var TITLE = 'RegExp: $+'; + +writeHeaderToLog('Executing script: RegExp_lastParen_as_array.js'); +writeHeaderToLog( SECTION + " "+ TITLE); + +// 'abcd'.match(/(abc)d/); RegExp['$+'] +'abcd'.match(/(abc)d/); +new TestCase ( "'abcd'.match(/(abc)d/); RegExp['$+']", + 'abc', RegExp['$+']); + +// 'abcd'.match(/(bcd)e/); RegExp['$+'] +'abcd'.match(/(bcd)e/); +new TestCase ( "'abcd'.match(/(bcd)e/); RegExp['$+']", + 'abc', RegExp['$+']); + +// 'abcdefg'.match(/(a(b(c(d)e)f)g)/); RegExp['$+'] +'abcdefg'.match(/(a(b(c(d)e)f)g)/); +new TestCase ( "'abcdefg'.match(/(a(b(c(d)e)f)g)/); RegExp['$+']", + 'd', RegExp['$+']); + +// 'abcdefg'.match(new RegExp('(a(b(c(d)e)f)g)')); RegExp['$+'] +'abcdefg'.match(new RegExp('(a(b(c(d)e)f)g)')); +new TestCase ( "'abcdefg'.match(new RegExp('(a(b(c(d)e)f)g)')); RegExp['$+']", + 'd', RegExp['$+']); + +// 'abcdefg'.match(/(a(b)c)(d(e)f)/); RegExp['$+'] +'abcdefg'.match(/(a(b)c)(d(e)f)/); +new TestCase ( "'abcdefg'.match(/(a(b)c)(d(e)f)/); RegExp['$+']", + 'e', RegExp['$+']); + +// 'abcdefg'.match(/(^)abc/); RegExp['$+'] +'abcdefg'.match(/(^)abc/); +new TestCase ( "'abcdefg'.match(/(^)abc/); RegExp['$+']", + '', RegExp['$+']); + +// 'abcdefg'.match(/(^a)bc/); RegExp['$+'] +'abcdefg'.match(/(^a)bc/); +new TestCase ( "'abcdefg'.match(/(^a)bc/); RegExp['$+']", + 'a', RegExp['$+']); + +// 'abcdefg'.match(new RegExp('(^a)bc')); RegExp['$+'] +'abcdefg'.match(new RegExp('(^a)bc')); +new TestCase ( "'abcdefg'.match(new RegExp('(^a)bc')); RegExp['$+']", + 'a', RegExp['$+']); + +// 'abcdefg'.match(/bc/); RegExp['$+'] +'abcdefg'.match(/bc/); +new TestCase ( "'abcdefg'.match(/bc/); RegExp['$+']", + '', RegExp['$+']); + +test(); diff --git a/js/src/tests/non262/RegExp/RegExp_leftContext.js b/js/src/tests/non262/RegExp/RegExp_leftContext.js new file mode 100644 index 0000000000..616f0a3e00 --- /dev/null +++ b/js/src/tests/non262/RegExp/RegExp_leftContext.js @@ -0,0 +1,56 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + Filename: RegExp_leftContext.js + Description: 'Tests RegExps leftContext property' + + Author: Nick Lerissa + Date: March 12, 1998 +*/ + +var SECTION = 'As described in Netscape doc "Whats new in JavaScript 1.2"'; +var TITLE = 'RegExp: leftContext'; + +writeHeaderToLog('Executing script: RegExp_leftContext.js'); +writeHeaderToLog( SECTION + " "+ TITLE); + +// 'abc123xyz'.match(/123/); RegExp.leftContext +'abc123xyz'.match(/123/); +new TestCase ( "'abc123xyz'.match(/123/); RegExp.leftContext", + 'abc', RegExp.leftContext); + +// 'abc123xyz'.match(/456/); RegExp.leftContext +'abc123xyz'.match(/456/); +new TestCase ( "'abc123xyz'.match(/456/); RegExp.leftContext", + 'abc', RegExp.leftContext); + +// 'abc123xyz'.match(/abc123xyz/); RegExp.leftContext +'abc123xyz'.match(/abc123xyz/); +new TestCase ( "'abc123xyz'.match(/abc123xyz/); RegExp.leftContext", + '', RegExp.leftContext); + +// 'xxxx'.match(/$/); RegExp.leftContext +'xxxx'.match(/$/); +new TestCase ( "'xxxx'.match(/$/); RegExp.leftContext", + 'xxxx', RegExp.leftContext); + +// 'test'.match(/^/); RegExp.leftContext +'test'.match(/^/); +new TestCase ( "'test'.match(/^/); RegExp.leftContext", + '', RegExp.leftContext); + +// 'xxxx'.match(new RegExp('$')); RegExp.leftContext +'xxxx'.match(new RegExp('$')); +new TestCase ( "'xxxx'.match(new RegExp('$')); RegExp.leftContext", + 'xxxx', RegExp.leftContext); + +// 'test'.match(new RegExp('^')); RegExp.leftContext +'test'.match(new RegExp('^')); +new TestCase ( "'test'.match(new RegExp('^')); RegExp.leftContext", + '', RegExp.leftContext); + +test(); diff --git a/js/src/tests/non262/RegExp/RegExp_leftContext_as_array.js b/js/src/tests/non262/RegExp/RegExp_leftContext_as_array.js new file mode 100644 index 0000000000..04e7948476 --- /dev/null +++ b/js/src/tests/non262/RegExp/RegExp_leftContext_as_array.js @@ -0,0 +1,56 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + Filename: RegExp_leftContext_as_array.js + Description: 'Tests RegExps leftContext property (same tests as RegExp_leftContext.js but using $`)' + + Author: Nick Lerissa + Date: March 12, 1998 +*/ + +var SECTION = 'As described in Netscape doc "Whats new in JavaScript 1.2"'; +var TITLE = 'RegExp: $`'; + +writeHeaderToLog('Executing script: RegExp_leftContext_as_array.js'); +writeHeaderToLog( SECTION + " "+ TITLE); + +// 'abc123xyz'.match(/123/); RegExp['$`'] +'abc123xyz'.match(/123/); +new TestCase ( "'abc123xyz'.match(/123/); RegExp['$`']", + 'abc', RegExp['$`']); + +// 'abc123xyz'.match(/456/); RegExp['$`'] +'abc123xyz'.match(/456/); +new TestCase ( "'abc123xyz'.match(/456/); RegExp['$`']", + 'abc', RegExp['$`']); + +// 'abc123xyz'.match(/abc123xyz/); RegExp['$`'] +'abc123xyz'.match(/abc123xyz/); +new TestCase ( "'abc123xyz'.match(/abc123xyz/); RegExp['$`']", + '', RegExp['$`']); + +// 'xxxx'.match(/$/); RegExp['$`'] +'xxxx'.match(/$/); +new TestCase ( "'xxxx'.match(/$/); RegExp['$`']", + 'xxxx', RegExp['$`']); + +// 'test'.match(/^/); RegExp['$`'] +'test'.match(/^/); +new TestCase ( "'test'.match(/^/); RegExp['$`']", + '', RegExp['$`']); + +// 'xxxx'.match(new RegExp('$')); RegExp['$`'] +'xxxx'.match(new RegExp('$')); +new TestCase ( "'xxxx'.match(new RegExp('$')); RegExp['$`']", + 'xxxx', RegExp['$`']); + +// 'test'.match(new RegExp('^')); RegExp['$`'] +'test'.match(new RegExp('^')); +new TestCase ( "'test'.match(new RegExp('^')); RegExp['$`']", + '', RegExp['$`']); + +test(); diff --git a/js/src/tests/non262/RegExp/RegExp_object.js b/js/src/tests/non262/RegExp/RegExp_object.js new file mode 100644 index 0000000000..69fe4946ad --- /dev/null +++ b/js/src/tests/non262/RegExp/RegExp_object.js @@ -0,0 +1,54 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + Filename: RegExp_object.js + Description: 'Tests regular expressions creating RexExp Objects' + + Author: Nick Lerissa + Date: March 10, 1998 +*/ + +var SECTION = 'As described in Netscape doc "Whats new in JavaScript 1.2"'; +var TITLE = 'RegExp: object'; + +writeHeaderToLog('Executing script: RegExp_object.js'); +writeHeaderToLog( SECTION + " "+ TITLE); + +var SSN_pattern = new RegExp("\\d{3}-\\d{2}-\\d{4}"); + +// testing SSN pattern +new TestCase ( "'Test SSN is 123-34-4567'.match(SSN_pattern))", + String(["123-34-4567"]), String('Test SSN is 123-34-4567'.match(SSN_pattern))); + +// testing SSN pattern +new TestCase ( "'Test SSN is 123-34-4567'.match(SSN_pattern))", + String(["123-34-4567"]), String('Test SSN is 123-34-4567'.match(SSN_pattern))); + +var PHONE_pattern = new RegExp("\\(?(\\d{3})\\)?-?(\\d{3})-(\\d{4})"); +// testing PHONE pattern +new TestCase ( "'Our phone number is (408)345-2345.'.match(PHONE_pattern))", + String(["(408)345-2345","408","345","2345"]), String('Our phone number is (408)345-2345.'.match(PHONE_pattern))); + +// testing PHONE pattern +new TestCase ( "'The phone number is 408-345-2345!'.match(PHONE_pattern))", + String(["408-345-2345","408","345","2345"]), String('The phone number is 408-345-2345!'.match(PHONE_pattern))); + +// testing PHONE pattern +new TestCase ( "String(PHONE_pattern.toString())", + "/\\(?(\\d{3})\\)?-?(\\d{3})-(\\d{4})/", String(PHONE_pattern.toString())); + +// testing conversion to String +new TestCase ( "PHONE_pattern + ' is the string'", + "/\\(?(\\d{3})\\)?-?(\\d{3})-(\\d{4})/ is the string",PHONE_pattern + ' is the string'); + +// testing conversion to int +new TestCase ( "SSN_pattern - 8", + NaN,SSN_pattern - 8); + +var testPattern = new RegExp("(\\d+)45(\\d+)90"); + +test(); diff --git a/js/src/tests/non262/RegExp/RegExp_rightContext.js b/js/src/tests/non262/RegExp/RegExp_rightContext.js new file mode 100644 index 0000000000..131e989ad1 --- /dev/null +++ b/js/src/tests/non262/RegExp/RegExp_rightContext.js @@ -0,0 +1,56 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + Filename: RegExp_rightContext.js + Description: 'Tests RegExps rightContext property' + + Author: Nick Lerissa + Date: March 12, 1998 +*/ + +var SECTION = 'As described in Netscape doc "Whats new in JavaScript 1.2"'; +var TITLE = 'RegExp: rightContext'; + +writeHeaderToLog('Executing script: RegExp_rightContext.js'); +writeHeaderToLog( SECTION + " "+ TITLE); + +// 'abc123xyz'.match(/123/); RegExp.rightContext +'abc123xyz'.match(/123/); +new TestCase ( "'abc123xyz'.match(/123/); RegExp.rightContext", + 'xyz', RegExp.rightContext); + +// 'abc123xyz'.match(/456/); RegExp.rightContext +'abc123xyz'.match(/456/); +new TestCase ( "'abc123xyz'.match(/456/); RegExp.rightContext", + 'xyz', RegExp.rightContext); + +// 'abc123xyz'.match(/abc123xyz/); RegExp.rightContext +'abc123xyz'.match(/abc123xyz/); +new TestCase ( "'abc123xyz'.match(/abc123xyz/); RegExp.rightContext", + '', RegExp.rightContext); + +// 'xxxx'.match(/$/); RegExp.rightContext +'xxxx'.match(/$/); +new TestCase ( "'xxxx'.match(/$/); RegExp.rightContext", + '', RegExp.rightContext); + +// 'test'.match(/^/); RegExp.rightContext +'test'.match(/^/); +new TestCase ( "'test'.match(/^/); RegExp.rightContext", + 'test', RegExp.rightContext); + +// 'xxxx'.match(new RegExp('$')); RegExp.rightContext +'xxxx'.match(new RegExp('$')); +new TestCase ( "'xxxx'.match(new RegExp('$')); RegExp.rightContext", + '', RegExp.rightContext); + +// 'test'.match(new RegExp('^')); RegExp.rightContext +'test'.match(new RegExp('^')); +new TestCase ( "'test'.match(new RegExp('^')); RegExp.rightContext", + 'test', RegExp.rightContext); + +test(); diff --git a/js/src/tests/non262/RegExp/RegExp_rightContext_as_array.js b/js/src/tests/non262/RegExp/RegExp_rightContext_as_array.js new file mode 100644 index 0000000000..34dbcaac4d --- /dev/null +++ b/js/src/tests/non262/RegExp/RegExp_rightContext_as_array.js @@ -0,0 +1,56 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + Filename: RegExp_rightContext_as_array.js + Description: 'Tests RegExps $\' property (same tests as RegExp_rightContext.js but using $\)' + + Author: Nick Lerissa + Date: March 12, 1998 +*/ + +var SECTION = 'As described in Netscape doc "Whats new in JavaScript 1.2"'; +var TITLE = 'RegExp: $\''; + +writeHeaderToLog('Executing script: RegExp_rightContext.js'); +writeHeaderToLog( SECTION + " "+ TITLE); + +// 'abc123xyz'.match(/123/); RegExp['$\''] +'abc123xyz'.match(/123/); +new TestCase ( "'abc123xyz'.match(/123/); RegExp['$\'']", + 'xyz', RegExp['$\'']); + +// 'abc123xyz'.match(/456/); RegExp['$\''] +'abc123xyz'.match(/456/); +new TestCase ( "'abc123xyz'.match(/456/); RegExp['$\'']", + 'xyz', RegExp['$\'']); + +// 'abc123xyz'.match(/abc123xyz/); RegExp['$\''] +'abc123xyz'.match(/abc123xyz/); +new TestCase ( "'abc123xyz'.match(/abc123xyz/); RegExp['$\'']", + '', RegExp['$\'']); + +// 'xxxx'.match(/$/); RegExp['$\''] +'xxxx'.match(/$/); +new TestCase ( "'xxxx'.match(/$/); RegExp['$\'']", + '', RegExp['$\'']); + +// 'test'.match(/^/); RegExp['$\''] +'test'.match(/^/); +new TestCase ( "'test'.match(/^/); RegExp['$\'']", + 'test', RegExp['$\'']); + +// 'xxxx'.match(new RegExp('$')); RegExp['$\''] +'xxxx'.match(new RegExp('$')); +new TestCase ( "'xxxx'.match(new RegExp('$')); RegExp['$\'']", + '', RegExp['$\'']); + +// 'test'.match(new RegExp('^')); RegExp['$\''] +'test'.match(new RegExp('^')); +new TestCase ( "'test'.match(new RegExp('^')); RegExp['$\'']", + 'test', RegExp['$\'']); + +test(); diff --git a/js/src/tests/non262/RegExp/browser.js b/js/src/tests/non262/RegExp/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/RegExp/character-class-escape-s.js b/js/src/tests/non262/RegExp/character-class-escape-s.js new file mode 100644 index 0000000000..88514c4dda --- /dev/null +++ b/js/src/tests/non262/RegExp/character-class-escape-s.js @@ -0,0 +1,54 @@ +/* Generated by make_unicode.py DO NOT MODIFY */ +/* Unicode version: 15.0.0 */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ +var onlySpace = String.fromCodePoint( + 0x0009 /* (CHARACTER TABULATION) */, + 0x000A /* (LINE FEED (LF)) */, + 0x000B /* (LINE TABULATION) */, + 0x000C /* (FORM FEED (FF)) */, + 0x000D /* (CARRIAGE RETURN (CR)) */, + 0x0020 /* SPACE */, + 0x00A0 /* NO-BREAK SPACE (NON-BREAKING SPACE) */, + 0x1680 /* OGHAM SPACE MARK */, + 0x2000 /* EN QUAD */, + 0x2001 /* EM QUAD */, + 0x2002 /* EN SPACE */, + 0x2003 /* EM SPACE */, + 0x2004 /* THREE-PER-EM SPACE */, + 0x2005 /* FOUR-PER-EM SPACE */, + 0x2006 /* SIX-PER-EM SPACE */, + 0x2007 /* FIGURE SPACE */, + 0x2008 /* PUNCTUATION SPACE */, + 0x2009 /* THIN SPACE */, + 0x200A /* HAIR SPACE */, + 0x2028 /* LINE SEPARATOR */, + 0x2029 /* PARAGRAPH SEPARATOR */, + 0x202F /* NARROW NO-BREAK SPACE */, + 0x205F /* MEDIUM MATHEMATICAL SPACE */, + 0x3000 /* IDEOGRAPHIC SPACE */, + 0xFEFF /* ZERO WIDTH NO-BREAK SPACE (BYTE ORDER MARK) */ +); + +assertEq(/^\s+$/.exec(onlySpace) !== null, true); +assertEq(/^[\s]+$/.exec(onlySpace) !== null, true); +assertEq(/^[^\s]+$/.exec(onlySpace) === null, true); + +assertEq(/^\S+$/.exec(onlySpace) === null, true); +assertEq(/^[\S]+$/.exec(onlySpace) === null, true); +assertEq(/^[^\S]+$/.exec(onlySpace) !== null, true); + +// Also test with Unicode RegExps. +assertEq(/^\s+$/u.exec(onlySpace) !== null, true); +assertEq(/^[\s]+$/u.exec(onlySpace) !== null, true); +assertEq(/^[^\s]+$/u.exec(onlySpace) === null, true); + +assertEq(/^\S+$/u.exec(onlySpace) === null, true); +assertEq(/^[\S]+$/u.exec(onlySpace) === null, true); +assertEq(/^[^\S]+$/u.exec(onlySpace) !== null, true); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/character-escape-class-s-mongolian-vowel-separator.js b/js/src/tests/non262/RegExp/character-escape-class-s-mongolian-vowel-separator.js new file mode 100644 index 0000000000..d7a8b980da --- /dev/null +++ b/js/src/tests/non262/RegExp/character-escape-class-s-mongolian-vowel-separator.js @@ -0,0 +1,25 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var mongolian_vowel_separator = "\u180e"; + +assertEq(/^\s+$/.exec(mongolian_vowel_separator) === null, true); +assertEq(/^[\s]+$/.exec(mongolian_vowel_separator) === null, true); +assertEq(/^[^\s]+$/.exec(mongolian_vowel_separator) !== null, true); + +assertEq(/^\S+$/.exec(mongolian_vowel_separator) !== null, true); +assertEq(/^[\S]+$/.exec(mongolian_vowel_separator) !== null, true); +assertEq(/^[^\S]+$/.exec(mongolian_vowel_separator) === null, true); + +// Also test with Unicode RegExps. +assertEq(/^\s+$/u.exec(mongolian_vowel_separator) === null, true); +assertEq(/^[\s]+$/u.exec(mongolian_vowel_separator) === null, true); +assertEq(/^[^\s]+$/u.exec(mongolian_vowel_separator) !== null, true); + +assertEq(/^\S+$/u.exec(mongolian_vowel_separator) !== null, true); +assertEq(/^[\S]+$/u.exec(mongolian_vowel_separator) !== null, true); +assertEq(/^[^\S]+$/u.exec(mongolian_vowel_separator) === null, true); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/class-null.js b/js/src/tests/non262/RegExp/class-null.js new file mode 100644 index 0000000000..c95e5a4d79 --- /dev/null +++ b/js/src/tests/non262/RegExp/class-null.js @@ -0,0 +1,15 @@ +var BUGNUMBER = 1279467; +var summary = "Null in character class in RegExp with unicode flag."; + +print(BUGNUMBER + ": " + summary); + +var m = /([\0]+)/u.exec("\u0000"); +assertEq(m.length, 2); +assertEq(m[0], '\u0000'); +assertEq(m[1], '\u0000'); + +var m = /([\0]+)/u.exec("0"); +assertEq(m, null); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/compile-lastIndex.js b/js/src/tests/non262/RegExp/compile-lastIndex.js new file mode 100644 index 0000000000..5bd7e0b983 --- /dev/null +++ b/js/src/tests/non262/RegExp/compile-lastIndex.js @@ -0,0 +1,82 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 1253099; +var summary = + "RegExp.prototype.compile must perform all its steps *except* setting " + + ".lastIndex, then throw, when provided a RegExp whose .lastIndex has been " + + "made non-writable"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var regex = /foo/i; + +// Aside from making .lastIndex non-writable, this has one incidental effect +// ubiquitously tested through the remainder of this test: +// +// * RegExp.prototype.compile will do everything it ordinarily does, BUT it +// will throw a TypeError when attempting to zero .lastIndex immediately +// before succeeding overall. +// +// Ain't it great? +Object.defineProperty(regex, "lastIndex", { value: 42, writable: false }); + +assertEq(regex.global, false); +assertEq(regex.ignoreCase, true); +assertEq(regex.multiline, false); +assertEq(regex.unicode, false); +assertEq(regex.sticky, false); +assertEq(Object.getOwnPropertyDescriptor(regex, "lastIndex").writable, false); +assertEq(regex.lastIndex, 42); + +assertEq(regex.test("foo"), true); +assertEq(regex.test("FOO"), true); +assertEq(regex.test("bar"), false); +assertEq(regex.test("BAR"), false); + +assertThrowsInstanceOf(() => regex.compile("bar"), TypeError); + +assertEq(regex.global, false); +assertEq(regex.ignoreCase, false); +assertEq(regex.multiline, false); +assertEq(regex.unicode, false); +assertEq(regex.sticky, false); +assertEq(Object.getOwnPropertyDescriptor(regex, "lastIndex").writable, false); +assertEq(regex.lastIndex, 42); +assertEq(regex.test("foo"), false); +assertEq(regex.test("FOO"), false); +assertEq(regex.test("bar"), true); +assertEq(regex.test("BAR"), false); + +assertThrowsInstanceOf(() => regex.compile("^baz", "m"), TypeError); + +assertEq(regex.global, false); +assertEq(regex.ignoreCase, false); +assertEq(regex.multiline, true); +assertEq(regex.unicode, false); +assertEq(regex.sticky, false); +assertEq(Object.getOwnPropertyDescriptor(regex, "lastIndex").writable, false); +assertEq(regex.lastIndex, 42); +assertEq(regex.test("foo"), false); +assertEq(regex.test("FOO"), false); +assertEq(regex.test("bar"), false); +assertEq(regex.test("BAR"), false); +assertEq(regex.test("baz"), true); +assertEq(regex.test("BAZ"), false); +assertEq(regex.test("012345678901234567890123456789012345678901baz"), false); +assertEq(regex.test("012345678901234567890123456789012345678901\nbaz"), true); +assertEq(regex.test("012345678901234567890123456789012345678901BAZ"), false); +assertEq(regex.test("012345678901234567890123456789012345678901\nBAZ"), false); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/RegExp/compile-symbol.js b/js/src/tests/non262/RegExp/compile-symbol.js new file mode 100644 index 0000000000..9eea1124c8 --- /dev/null +++ b/js/src/tests/non262/RegExp/compile-symbol.js @@ -0,0 +1,14 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +for (let sym of [Symbol.iterator, Symbol(), Symbol("description")]) { + let re = /a/; + + assertEq(re.source, "a"); + assertThrowsInstanceOf(() => re.compile(sym), TypeError); + assertEq(re.source, "a"); +} + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/RegExp/constructor-IsRegExp.js b/js/src/tests/non262/RegExp/constructor-IsRegExp.js new file mode 100644 index 0000000000..8c735e4b97 --- /dev/null +++ b/js/src/tests/non262/RegExp/constructor-IsRegExp.js @@ -0,0 +1,86 @@ +var BUGNUMBER = 1147817; +var summary = "RegExp constructor with pattern with @@match."; + +print(BUGNUMBER + ": " + summary); + +var matchValue; +var constructorValue; + +var matchGet; +var constructorGet; +var sourceGet; +var flagsGet; +function reset() { + matchGet = false; + constructorGet = false; + sourceGet = false; + flagsGet = false; +} +var obj = { + get [Symbol.match]() { + matchGet = true; + return matchValue; + }, + get constructor() { + constructorGet = true; + return constructorValue; + }, + get source() { + sourceGet = true; + return "foo"; + }, + get flags() { + flagsGet = true; + return "i"; + }, + toString() { + return "bar"; + } +}; + +matchValue = true; +constructorValue = function() {}; + +reset(); +assertEq(RegExp(obj).toString(), "/foo/i"); +assertEq(matchGet, true); +assertEq(constructorGet, true); +assertEq(sourceGet, true); +assertEq(flagsGet, true); + +reset(); +assertEq(RegExp(obj, "g").toString(), "/foo/g"); +assertEq(matchGet, true); +assertEq(constructorGet, false); +assertEq(sourceGet, true); +assertEq(flagsGet, false); + +matchValue = false; +constructorValue = function() {}; + +reset(); +assertEq(RegExp(obj).toString(), "/bar/"); +assertEq(matchGet, true); +assertEq(constructorGet, false); +assertEq(sourceGet, false); +assertEq(flagsGet, false); + +reset(); +assertEq(RegExp(obj, "g").toString(), "/bar/g"); +assertEq(matchGet, true); +assertEq(constructorGet, false); +assertEq(sourceGet, false); +assertEq(flagsGet, false); + +matchValue = true; +constructorValue = RegExp; + +reset(); +assertEq(RegExp(obj), obj); +assertEq(matchGet, true); +assertEq(constructorGet, true); +assertEq(sourceGet, false); +assertEq(flagsGet, false); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/constructor-constructor.js b/js/src/tests/non262/RegExp/constructor-constructor.js new file mode 100644 index 0000000000..528f4978c2 --- /dev/null +++ b/js/src/tests/non262/RegExp/constructor-constructor.js @@ -0,0 +1,78 @@ +var BUGNUMBER = 1147817; +var summary = "RegExp constructor should check pattern.constructor."; + +print(BUGNUMBER + ": " + summary); + +var g = newGlobal(); + +var re = /foo/; +assertEq(RegExp(re), re); +re.constructor = 10; +assertEq(RegExp(re) === re, false); +assertEq(RegExp(re).toString(), re.toString()); + +// If pattern comes from different global, RegExp shouldn't return it. +re = g.eval(`var re = /foo/; re;`); +assertEq(RegExp(re) === re, false); +assertEq(RegExp(re).toString(), re.toString()); +g.eval(`re.constructor = 10;`); +assertEq(RegExp(re) === re, false); +assertEq(RegExp(re).toString(), re.toString()); + + +re = new Proxy(/a/, { + get(that, name) { + return that[name]; + } +}); +assertEq(RegExp(re), re); +re = new Proxy(/a/, { + get(that, name) { + if (name == "constructor") { + return function() {}; + } + return that[name]; + } +}); +assertEq(RegExp(re) === re, false); +re = new Proxy(/a/, { + get(that, name) { + if (name == Symbol.match) { + return undefined; + } + return that[name]; + } +}); +assertEq(RegExp(re) === re, false); + +re = new Proxy(g.eval(`/a/`), { + get(that, name) { + return that[name]; + } +}); +assertEq(RegExp(re) === re, false); + +re = g.eval(`new Proxy(/a/, { + get(that, name) { + return that[name]; + } +});`); +assertEq(RegExp(re) === re, false); + + +var obj = { [Symbol.match]: true, source: "foo", flags: "gi" }; +assertEq(RegExp(obj) === obj, false); +assertEq(RegExp(obj).toString(), "/foo/gi"); +obj.constructor = RegExp; +assertEq(RegExp(obj), obj); + +obj = g.eval(`var obj = { [Symbol.match]: true, source: "foo", flags: "gi" }; obj;`); +assertEq(RegExp(obj) === obj, false); +assertEq(RegExp(obj).toString(), "/foo/gi"); +g.eval(`obj.constructor = RegExp`); +assertEq(RegExp(obj) === obj, false); +obj.constructor = RegExp; +assertEq(RegExp(obj), obj); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/constructor-ordering-2.js b/js/src/tests/non262/RegExp/constructor-ordering-2.js new file mode 100644 index 0000000000..21a6bbeca7 --- /dev/null +++ b/js/src/tests/non262/RegExp/constructor-ordering-2.js @@ -0,0 +1,21 @@ +// Make sure that we don't ToString the second argument until /after/ doing +// the appropriate subclassing lookups + +var didLookup = false; + +var re = /a/; +var flags = { toString() { assertEq(didLookup, true); return "g"; } }; +var newRe = Reflect.construct(RegExp, [re, flags], + Object.defineProperty(function(){}.bind(null), "prototype", { + get() { + didLookup = true; + return RegExp.prototype; + } +})); + +assertEq(Object.getPrototypeOf(newRe), RegExp.prototype); +assertEq(didLookup, true); + + +if (typeof reportCompare === 'function') + reportCompare(0,0,"OK"); diff --git a/js/src/tests/non262/RegExp/constructor-ordering.js b/js/src/tests/non262/RegExp/constructor-ordering.js new file mode 100644 index 0000000000..3e3a9b695b --- /dev/null +++ b/js/src/tests/non262/RegExp/constructor-ordering.js @@ -0,0 +1,16 @@ +// Make sure that we don't misorder subclassing accesses with respect to +// accessing regex arg internal slots +// +// Test credit André Bargull. + +var re = /a/; +var newRe = Reflect.construct(RegExp, [re], Object.defineProperty(function(){}.bind(null), "prototype", { + get() { + re.compile("b"); + return RegExp.prototype; + } +})); +assertEq(newRe.source, "a"); + +if (typeof reportCompare === 'function') + reportCompare(0,0,"OK"); diff --git a/js/src/tests/non262/RegExp/constructor-regexp-unicode.js b/js/src/tests/non262/RegExp/constructor-regexp-unicode.js new file mode 100644 index 0000000000..b348c34a01 --- /dev/null +++ b/js/src/tests/non262/RegExp/constructor-regexp-unicode.js @@ -0,0 +1,9 @@ +var BUGNUMBER = 1274393; +var summary = "RegExp constructor should check the pattern syntax again when adding unicode flag."; + +print(BUGNUMBER + ": " + summary); + +assertThrowsInstanceOf(() => RegExp(/\-/, "u"), SyntaxError); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/constructor-regexp.js b/js/src/tests/non262/RegExp/constructor-regexp.js new file mode 100644 index 0000000000..419b027138 --- /dev/null +++ b/js/src/tests/non262/RegExp/constructor-regexp.js @@ -0,0 +1,61 @@ +var BUGNUMBER = 1130860; +var summary = "RegExp constructor shouldn't invoke source/flags getters on argument RegExp instance."; + +print(BUGNUMBER + ": " + summary); + +// same-compartment +var a = /foo/; +var flagsCalled = false; +var sourceCalled = false; +Object.defineProperty(a, "source", { get: () => { + sourceCalled = true; + return "bar"; +}}); +Object.defineProperty(a, "flags", { get: () => { + flagsCalled = true; + return "i"; +}}); + +assertEq(a.source, "bar"); +assertEq(a.flags, "i"); +assertEq(sourceCalled, true); +assertEq(flagsCalled, true); + +sourceCalled = false; +flagsCalled = false; +assertEq(new RegExp(a).source, "foo"); +assertEq(sourceCalled, false); +assertEq(flagsCalled, false); + +// cross-compartment +var g = newGlobal(); +var b = g.eval(` +var b = /foo2/; +var flagsCalled = false; +var sourceCalled = false; +Object.defineProperty(b, "source", { get: () => { + sourceCalled = true; + return "bar2"; +}}); +Object.defineProperty(b, "flags", { get: () => { + flagsCalled = true; + return "i"; +}}); +b; +`); + +assertEq(b.source, "bar2"); +assertEq(b.flags, "i"); +assertEq(g.eval("sourceCalled;"), true); +assertEq(g.eval("flagsCalled;"), true); + +g.eval(` +sourceCalled = false; +flagsCalled = false; +`); +assertEq(new RegExp(b).source, "foo2"); +assertEq(g.eval("sourceCalled;"), false); +assertEq(g.eval("flagsCalled;"), false); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/constructor-symbol.js b/js/src/tests/non262/RegExp/constructor-symbol.js new file mode 100644 index 0000000000..503d7e5a85 --- /dev/null +++ b/js/src/tests/non262/RegExp/constructor-symbol.js @@ -0,0 +1,14 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +for (let sym of [Symbol.iterator, Symbol(), Symbol("description")]) { + assertThrowsInstanceOf(() => RegExp(sym), TypeError); + assertThrowsInstanceOf(() => new RegExp(sym), TypeError); + + assertThrowsInstanceOf(() => RegExp(sym, "g"), TypeError); + assertThrowsInstanceOf(() => new RegExp(sym, "g"), TypeError); +} + +if (typeof reportCompare === 'function') + reportCompare(0, 0); diff --git a/js/src/tests/non262/RegExp/control_characters.js b/js/src/tests/non262/RegExp/control_characters.js new file mode 100644 index 0000000000..dcef462a9a --- /dev/null +++ b/js/src/tests/non262/RegExp/control_characters.js @@ -0,0 +1,39 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + Filename: control_characters.js + Description: 'Tests regular expressions containing .' + + Author: Nick Lerissa + Date: April 8, 1998 +*/ + +var SECTION = 'As described in Netscape doc "Whats new in JavaScript 1.2"'; +var TITLE = 'RegExp: .'; +var BUGNUMBER="123802"; + +printBugNumber(BUGNUMBER); +writeHeaderToLog('Executing script: control_characters.js'); +writeHeaderToLog( SECTION + " "+ TITLE); + + +// 'àOÐ ê:i¢Ø'.match(new RegExp('.+')) +new TestCase ( "'àOÐ ê:i¢Ø'.match(new RegExp('.+'))", + String(['àOÐ ê:i¢Ø']), String('àOÐ ê:i¢Ø'.match(new RegExp('.+')))); + +// string1.match(new RegExp(string1)) +var string1 = 'àOÐ ê:i¢Ø'; +new TestCase ( "string1 = " + string1 + " string1.match(string1)", + String([string1]), String(string1.match(string1))); + +string1 = ""; +for (var i = 0; i < 32; i++) + string1 += String.fromCharCode(i); +new TestCase ( "string1 = " + string1 + " string1.match(string1)", + String([string1]), String(string1.match(string1))); + +test(); diff --git a/js/src/tests/non262/RegExp/cross-compartment-getter.js b/js/src/tests/non262/RegExp/cross-compartment-getter.js new file mode 100644 index 0000000000..c625c63177 --- /dev/null +++ b/js/src/tests/non262/RegExp/cross-compartment-getter.js @@ -0,0 +1,43 @@ +const otherGlobal = newGlobal({newCompartment: true}); + +let regExp = otherGlobal.eval("/a(b|c)/iy"); + +function get(name) { + const descriptor = Object.getOwnPropertyDescriptor(RegExp.prototype, name); + return descriptor.get.call(regExp); +} + +assertEq(get("flags"), "iy"); +assertEq(get("global"), false); +assertEq(get("ignoreCase"), true); +assertEq(get("multiline"), false); +assertEq(get("dotAll"), false); +assertEq(get("source"), "a(b|c)"); +assertEq(get("sticky"), true); +assertEq(get("unicode"), false); + +regExp = otherGlobal.eval("new RegExp('', 'gu')"); + +assertEq(get("flags"), "gu"); +assertEq(get("global"), true); +assertEq(get("ignoreCase"), false); +assertEq(get("multiline"), false); +assertEq(get("dotAll"), false); +assertEq(get("source"), "(?:)"); +assertEq(get("sticky"), false); +assertEq(get("unicode"), true); + +// Trigger escaping +regExp = otherGlobal.eval("new RegExp('a/b', '')"); + +assertEq(get("flags"), ""); +assertEq(get("global"), false); +assertEq(get("ignoreCase"), false); +assertEq(get("multiline"), false); +assertEq(get("dotAll"), false); +assertEq(get("source"), "a\\/b"); +assertEq(get("sticky"), false); +assertEq(get("unicode"), false); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/descriptor.js b/js/src/tests/non262/RegExp/descriptor.js new file mode 100644 index 0000000000..cc545b3a6a --- /dev/null +++ b/js/src/tests/non262/RegExp/descriptor.js @@ -0,0 +1,25 @@ +var BUGNUMBER = 1120169; +var summary = "Implement RegExp.prototype.{global, ignoreCase, multiline, sticky, unicode} - property descriptor"; + +print(BUGNUMBER + ": " + summary); + +var getters = [ + "flags", + "global", + "ignoreCase", + "multiline", + "source", + "sticky", + "unicode", +]; + +for (var name of getters) { + var desc = Object.getOwnPropertyDescriptor(RegExp.prototype, name); + assertEq(desc.configurable, true); + assertEq(desc.enumerable, false); + assertEq("writable" in desc, false); + assertEq("get" in desc, true); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/empty-lookahead.js b/js/src/tests/non262/RegExp/empty-lookahead.js new file mode 100644 index 0000000000..6e2f709e86 --- /dev/null +++ b/js/src/tests/non262/RegExp/empty-lookahead.js @@ -0,0 +1,8 @@ +//bug 473941 +var regexp; + +regexp = /(?=)/; +assertEq(regexp.test('test'), true); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/escape.js b/js/src/tests/non262/RegExp/escape.js new file mode 100644 index 0000000000..bb59b797d3 --- /dev/null +++ b/js/src/tests/non262/RegExp/escape.js @@ -0,0 +1,70 @@ +var BUGNUMBER = 1130860; +var summary = 'Slash and LineTerminator should be escaped correctly.'; + +print(BUGNUMBER + ": " + summary); + +function test(re, source) { + assertEq(re.source, source); + assertEq(eval("/" + re.source + "/").source, source); + assertEq(re.toString(), "/" + source + "/"); +} + +test(/\\n/, "\\\\n"); +test(/\\\n/, "\\\\\\n"); +test(/\\\\n/, "\\\\\\\\n"); +test(RegExp("\\n"), "\\n"); +test(RegExp("\\\n"), "\\n"); +test(RegExp("\\\\n"), "\\\\n"); + +test(/\\r/, "\\\\r"); +test(/\\\r/, "\\\\\\r"); +test(/\\\\r/, "\\\\\\\\r"); +test(RegExp("\\r"), "\\r"); +test(RegExp("\\\r"), "\\r"); +test(RegExp("\\\\r"), "\\\\r"); + +test(/\\u2028/, "\\\\u2028"); +test(/\\\u2028/, "\\\\\\u2028"); +test(/\\\\u2028/, "\\\\\\\\u2028"); +test(RegExp("\\u2028"), "\\u2028"); +test(RegExp("\\\u2028"), "\\u2028"); +test(RegExp("\\\\u2028"), "\\\\u2028"); + +test(/\\u2029/, "\\\\u2029"); +test(/\\\u2029/, "\\\\\\u2029"); +test(/\\\\u2029/, "\\\\\\\\u2029"); +test(RegExp("\\u2029"), "\\u2029"); +test(RegExp("\\\u2029"), "\\u2029"); +test(RegExp("\\\\u2029"), "\\\\u2029"); + +test(/\//, "\\/"); +test(/\\\//, "\\\\\\/"); +test(RegExp("/"), "\\/"); +test(RegExp("\/"), "\\/"); +test(RegExp("\\/"), "\\/"); +test(RegExp("\\\/"), "\\/"); +test(RegExp("\\\\/"), "\\\\\\/"); + +test(/[/]/, "[/]"); +test(/[\/]/, "[\\/]"); +test(/[\\/]/, "[\\\\/]"); +test(/[\\\/]/, "[\\\\\\/]"); +test(RegExp("[/]"), "[/]"); +test(RegExp("[\/]"), "[/]"); +test(RegExp("[\\/]"), "[\\/]"); +test(RegExp("[\\\/]"), "[\\/]"); +test(RegExp("[\\\\/]"), "[\\\\/]"); + +test(RegExp("\[/\]"), "[/]"); +test(RegExp("\[\\/\]"), "[\\/]"); + +test(/\[\/\]/, "\\[\\/\\]"); +test(/\[\\\/\]/, "\\[\\\\\\/\\]"); +test(RegExp("\\[/\\]"), "\\[\\/\\]"); +test(RegExp("\\[\/\\]"), "\\[\\/\\]"); +test(RegExp("\\[\\/\\]"), "\\[\\/\\]"); +test(RegExp("\\[\\\/\\]"), "\\[\\/\\]"); +test(RegExp("\\[\\\\/\\]"), "\\[\\\\\\/\\]"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/everything.js b/js/src/tests/non262/RegExp/everything.js new file mode 100644 index 0000000000..798eccc829 --- /dev/null +++ b/js/src/tests/non262/RegExp/everything.js @@ -0,0 +1,47 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + Filename: everything.js + Description: 'Tests regular expressions' + + Author: Nick Lerissa + Date: March 24, 1998 +*/ + +var SECTION = 'As described in Netscape doc "Whats new in JavaScript 1.2"'; +var TITLE = 'RegExp'; + +writeHeaderToLog('Executing script: everything.js'); +writeHeaderToLog( SECTION + " "+ TITLE); + + +// 'Sally and Fred are sure to come.'.match(/^[a-z\s]*/i) +new TestCase ( "'Sally and Fred are sure to come'.match(/^[a-z\\s]*/i)", + String(["Sally and Fred are sure to come"]), String('Sally and Fred are sure to come'.match(/^[a-z\s]*/i))); + +// 'test123W+xyz'.match(new RegExp('^[a-z]*[0-9]+[A-Z]?.(123|xyz)$')) +new TestCase ( "'test123W+xyz'.match(new RegExp('^[a-z]*[0-9]+[A-Z]?.(123|xyz)$'))", + String(["test123W+xyz","xyz"]), String('test123W+xyz'.match(new RegExp('^[a-z]*[0-9]+[A-Z]?.(123|xyz)$')))); + +// 'number one 12365 number two 9898'.match(/(\d+)\D+(\d+)/) +new TestCase ( "'number one 12365 number two 9898'.match(/(\d+)\D+(\d+)/)", + String(["12365 number two 9898","12365","9898"]), String('number one 12365 number two 9898'.match(/(\d+)\D+(\d+)/))); + +var simpleSentence = /(\s?[^\!\?\.]+[\!\?\.])+/; +// 'See Spot run.'.match(simpleSentence) +new TestCase ( "'See Spot run.'.match(simpleSentence)", + String(["See Spot run.","See Spot run."]), String('See Spot run.'.match(simpleSentence))); + +// 'I like it. What's up? I said NO!'.match(simpleSentence) +new TestCase ( "'I like it. What's up? I said NO!'.match(simpleSentence)", + String(["I like it. What's up? I said NO!",' I said NO!']), String('I like it. What\'s up? I said NO!'.match(simpleSentence))); + +// 'the quick brown fox jumped over the lazy dogs'.match(/((\w+)\s*)+/) +new TestCase ( "'the quick brown fox jumped over the lazy dogs'.match(/((\\w+)\\s*)+/)", + String(['the quick brown fox jumped over the lazy dogs','dogs','dogs']),String('the quick brown fox jumped over the lazy dogs'.match(/((\w+)\s*)+/))); + +test(); diff --git a/js/src/tests/non262/RegExp/exec-002.js b/js/src/tests/non262/RegExp/exec-002.js new file mode 100644 index 0000000000..d1293e81ec --- /dev/null +++ b/js/src/tests/non262/RegExp/exec-002.js @@ -0,0 +1,186 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + * File Name: RegExp/exec-002.js + * ECMA Section: 15.7.5.3 + * Description: Based on ECMA 2 Draft 7 February 1999 + * + * Test cases provided by rogerl@netscape.com + * + * Author: christine@netscape.com + * Date: 19 February 1999 + */ +var SECTION = "RegExp/exec-002"; +var TITLE = "RegExp.prototype.exec(string)"; + + +/* + * for each test case, verify: + * - type of object returned + * - length of the returned array + * - value of lastIndex + * - value of index + * - value of input + * - value of the array indices + */ + +AddRegExpCases( + /(a|d|q|)x/i, + "bcaDxqy", + 3, + ["Dx", "D"] ); + +AddRegExpCases( + /(a|(e|q))(x|y)/, + "bcaddxqy", + 6, + ["qy","q","q","y"] ); + + +AddRegExpCases( + /a+b+d/, + "aabbeeaabbs", + 0, + null ); + +AddRegExpCases( + /a*b/, + "aaadaabaaa", + 4, + ["aab"] ); + +AddRegExpCases( + /a*b/, + "dddb", + 3, + ["b"] ); + +AddRegExpCases( + /a*b/, + "xxx", + 0, + null ); + +AddRegExpCases( + /x\d\dy/, + "abcx45ysss235", + 3, + ["x45y"] ); + +AddRegExpCases( + /[^abc]def[abc]+/, + "abxdefbb", + 2, + ["xdefbb"] ); + +AddRegExpCases( + /(a*)baa/, + "ccdaaabaxaabaa", + 9, + ["aabaa", "aa"] ); + +AddRegExpCases( + /(a*)baa/, + "aabaa", + 0, + ["aabaa", "aa"] ); + +AddRegExpCases( + /q(a|b)*q/, + "xxqababqyy", + 2, + ["qababq", "b"] ); + +AddRegExpCases( + /(a(.|[^d])c)*/, + "adcaxc", + 0, + ["adcaxc", "axc", "x"] ); + +AddRegExpCases( + /(a*)b\1/, + "abaaaxaabaayy", + 0, + ["aba", "a"] ); + +AddRegExpCases( + /(a*)b\1/, + "abaaaxaabaayy", + 0, + ["aba", "a"] ); + +AddRegExpCases( + /(a*)b\1/, + "cccdaaabaxaabaayy", + 6, + ["aba", "a"] ); + +AddRegExpCases( + /(a*)b\1/, + "cccdaaabqxaabaayy", + 7, + ["b", ""] ); + +AddRegExpCases( + /"(.|[^"\\\\])*"/, + 'xx\"makudonarudo\"yy', + 2, + ["\"makudonarudo\"", "o"] ); + + AddRegExpCases( + /"(.|[^"\\\\])*"/, + "xx\"ma\"yy", + 2, + ["\"ma\"", "a"] ); + + test(); + + function AddRegExpCases( + regexp, pattern, index, matches_array ) { + +// prevent a runtime error + + if ( regexp.exec(pattern) == null || matches_array == null ) { + AddTestCase( + regexp + ".exec(" + pattern +")", + matches_array, + regexp.exec(pattern) ); + + return; + } + AddTestCase( + regexp + ".exec(" + pattern +").length", + matches_array.length, + regexp.exec(pattern).length ); + + AddTestCase( + regexp + ".exec(" + pattern +").index", + index, + regexp.exec(pattern).index ); + + AddTestCase( + regexp + ".exec(" + pattern +").input", + pattern, + regexp.exec(pattern).input ); + + AddTestCase( + regexp + ".exec(" + pattern +").toString()", + matches_array.toString(), + regexp.exec(pattern).toString() ); +/* + var limit = matches_array.length > regexp.exec(pattern).length + ? matches_array.length + : regexp.exec(pattern).length; + + for ( var matches = 0; matches < limit; matches++ ) { + AddTestCase( + regexp + ".exec(" + pattern +")[" + matches +"]", + matches_array[matches], + regexp.exec(pattern)[matches] ); + } +*/ + } diff --git a/js/src/tests/non262/RegExp/exec-lastIndex-ToInteger.js b/js/src/tests/non262/RegExp/exec-lastIndex-ToInteger.js new file mode 100644 index 0000000000..4505362d83 --- /dev/null +++ b/js/src/tests/non262/RegExp/exec-lastIndex-ToInteger.js @@ -0,0 +1,36 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * + * Author: Geoffrey Sneddon + */ + +var BUGNUMBER = 646490; +var summary = + "RegExp.prototype.exec doesn't get the lastIndex and ToInteger() it for " + + "non-global regular expressions when it should"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var re = /./, called = 0; +re.lastIndex = {valueOf: function() { called++; return 0; }}; +re.exec("."); +re.lastIndex = {toString: function() { called++; return "0"; }}; +re.exec("."); +re.lastIndex = { + valueOf: function() { called++; return 0; }, + toString: function() { called--; } +}; +re.exec("."); +assertEq(called, 3, "FAIL, got " + called); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/RegExp/exec-lastIndex-negative.js b/js/src/tests/non262/RegExp/exec-lastIndex-negative.js new file mode 100644 index 0000000000..18eb2ab9d9 --- /dev/null +++ b/js/src/tests/non262/RegExp/exec-lastIndex-negative.js @@ -0,0 +1,27 @@ +var BUGNUMBER = 1207922; +var summary = "negative lastIndex should be treated as 0."; + +print(BUGNUMBER + ": " + summary); + +var pattern = /abc/gi; +var string = 'AbcaBcabC'; + +var indices = [ + -1, + -Math.pow(2,32), + -(Math.pow(2,32) + 1), + -Math.pow(2,32) * 2, + -Math.pow(2,40), + -Number.MAX_VALUE, +]; +for (var index of indices) { + pattern.lastIndex = index; + var result = pattern.exec(string); + assertEq(result.index, 0); + assertEq(result.length, 1); + assertEq(result[0], "Abc"); + assertEq(pattern.lastIndex, 3); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/exec.js b/js/src/tests/non262/RegExp/exec.js new file mode 100644 index 0000000000..4284b6e014 --- /dev/null +++ b/js/src/tests/non262/RegExp/exec.js @@ -0,0 +1,240 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 646490; +var summary = + "RegExp.prototype.exec doesn't get the lastIndex and ToInteger() it for " + + "non-global regular expressions when it should"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function expectThrowTypeError(fun) +{ + try + { + var r = fun(); + throw new Error("didn't throw TypeError, returned " + r); + } + catch (e) + { + assertEq(e instanceof TypeError, true, + "didn't throw TypeError, got: " + e); + } +} + +function checkExec(description, regex, args, obj) +{ + var lastIndex = obj.lastIndex; + var index = obj.index; + var input = obj.input; + var indexArray = obj.indexArray; + + var res = regex.exec.apply(regex, args); + + assertEq(Array.isArray(res), true, description + ": not an array"); + assertEq(regex.lastIndex, lastIndex, description + ": wrong lastIndex"); + assertEq(res.index, index, description + ": wrong index"); + assertEq(res.input, input, description + ": wrong input"); + assertEq(res.length, indexArray.length, description + ": wrong length"); + for (var i = 0, sz = indexArray.length; i < sz; i++) + assertEq(res[i], indexArray[i], description + " " + i + ": wrong index value"); +} + +var exec = RegExp.prototype.exec; +var r, res, called, obj; + +/* 1. Let R be this RegExp object. */ +expectThrowTypeError(function() { exec.call(null); }); +expectThrowTypeError(function() { exec.call(""); }); +expectThrowTypeError(function() { exec.call(5); }); +expectThrowTypeError(function() { exec.call({}); }); +expectThrowTypeError(function() { exec.call([]); }); +expectThrowTypeError(function() { exec.call(); }); +expectThrowTypeError(function() { exec.call(true); }); +expectThrowTypeError(function() { exec.call(Object.create(RegExp.prototype)); }); +expectThrowTypeError(function() { exec.call(Object.create(/a/)); }); + + +/* 2. Let S be the value of ToString(string). */ +called = false; +r = /a/; +assertEq(r.lastIndex, 0); + +checkExec("/a/", r, [{ toString: function() { called = true; return 'ba'; } }], + { lastIndex: 0, + index: 1, + input: "ba", + indexArray: ["a"] }); +assertEq(called, true); + +called = false; +try +{ + res = r.exec({ toString: null, valueOf: function() { called = true; throw 17; } }); + throw new Error("didn't throw"); +} +catch (e) +{ + assertEq(e, 17); +} + +assertEq(called, true); + +called = false; +obj = r.lastIndex = { valueOf: function() { assertEq(true, false, "shouldn't have been called"); } }; +try +{ + res = r.exec({ toString: null, valueOf: function() { assertEq(called, false); called = true; throw 17; } }); + throw new Error("didn't throw"); +} +catch (e) +{ + assertEq(e, 17); +} + +assertEq(called, true); +assertEq(r.lastIndex, obj); + +// We don't test lack of an argument because of RegExp statics non-standard +// behaviors overriding what really should happen for lack of an argument, sigh. + + +/* + * 3. Let length be the length of S. + * 4. Let lastIndex be the result of calling the [[Get]] internal method of R with argument "lastIndex". + * 5. Let i be the value of ToInteger(lastIndex). + */ +r = /b/; +r.lastIndex = { valueOf: {}, toString: {} }; +expectThrowTypeError(function() { r.exec("foopy"); }); +r.lastIndex = { valueOf: function() { throw new TypeError(); } }; +expectThrowTypeError(function() { r.exec("foopy"); }); + + +/* + * 6. Let global be the result of calling the [[Get]] internal method of R with argument "global". + * 7. If global is false, then let i = 0. + */ +obj = { valueOf: function() { return 5; } }; +r = /abc/; +r.lastIndex = obj; + +checkExec("/abc/ take one", r, ["abc-------abc"], + { lastIndex: obj, + index: 0, + input: "abc-------abc", + indexArray: ["abc"] }); + +checkExec("/abc/ take two", r, ["abc-------abc"], + { lastIndex: obj, + index: 0, + input: "abc-------abc", + indexArray: ["abc"] }); + + +/* + * 8. Let matchSucceeded be false. + * 9. Repeat, while matchSucceeded is false + * a. If i < 0 or i > length, then + * i. Call the [[Put]] internal method of R with arguments "lastIndex", 0, and true. + * ii. Return null. + * b. Call the [[Match]] internal method of R with arguments S and i. + * c. If [[Match]] returned failure, then + * i. Let i = i+1. + * d. else + * i. Let r be the State result of the call to [[Match]]. + * ii. Set matchSucceeded to true. + * e. Let i = i+1. + */ +r = /abc()?/; +r.lastIndex = -5; +checkExec("/abc()?/ with lastIndex -5", r, ["abc-------abc"], + { lastIndex: -5, + index: 0, + input: "abc-------abc", + indexArray: ["abc", undefined] }); + + +r = /abc/; +r.lastIndex = -17; +res = r.exec("cdefg"); +assertEq(res, null); +assertEq(r.lastIndex, -17); + +r = /abc/g; +r.lastIndex = -42; +res = r.exec("cdefg"); +assertEq(res, null); +assertEq(r.lastIndex, 0); + + +/* + * 10. Let e be r's endIndex value. + * 11. If global is true, + * a. Call the [[Put]] internal method of R with arguments "lastIndex", e, and true. + */ +r = /abc/g; +r.lastIndex = 17; +assertEq(r.exec("sdfs"), null); +assertEq(r.lastIndex, 0); + +r = /abc/g; +r.lastIndex = 2; +checkExec("/abc/g", r, ["00abc"], + { lastIndex: 5, + index: 2, + input: "00abc", + indexArray: ["abc"] }); + + + +r = /a(b)c/g; +r.lastIndex = 2; +checkExec("/a(b)c/g take two", r, ["00abcd"], + { lastIndex: 5, + index: 2, + input: "00abcd", + indexArray: ["abc", "b"] }); + + +/* + * 12. Let n be the length of r's captures array. (This is the same value as + * 15.10.2.1's NCapturingParens.) + * 13. Let A be a new array created as if by the expression new Array() where + * Array is the standard built-in constructor with that name. + * 14. Let matchIndex be the position of the matched substring within the + * complete String S. + * 15. Call the [[DefineOwnProperty]] internal method of A with arguments + * "index", Property Descriptor {[[Value]]: matchIndex, [[Writable]: true, + * [[Enumerable]]: true, [[Configurable]]: true}, and true. + * 16. Call the [[DefineOwnProperty]] internal method of A with arguments + * "input", Property Descriptor {[[Value]]: S, [[Writable]: true, + * [[Enumerable]]: true, [[Configurable]]: true}, and true. + * 17. Call the [[DefineOwnProperty]] internal method of A with arguments + * "length", Property Descriptor {[[Value]]: n + 1}, and true. + * 18. Let matchedSubstr be the matched substring (i.e. the portion of S + * between offset i inclusive and offset e exclusive). + * 19. Call the [[DefineOwnProperty]] internal method of A with arguments "0", + * Property Descriptor {[[Value]]: matchedSubstr, [[Writable]: true, + * [[Enumerable]]: true, [[Configurable]]: true}, and true. + * 20. For each integer i such that I > 0 and I ≤ n + * a. Let captureI be i th element of r's captures array. + * b. Call the [[DefineOwnProperty]] internal method of A with arguments + * ToString(i), Property Descriptor {[[Value]]: captureI, [[Writable]: + * true, [[Enumerable]]: true, [[Configurable]]: true}, and true. + * 21. Return A. + */ +// throughout, above (and in other tests) + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/RegExp/flag-accessors.js b/js/src/tests/non262/RegExp/flag-accessors.js new file mode 100644 index 0000000000..848b916c50 --- /dev/null +++ b/js/src/tests/non262/RegExp/flag-accessors.js @@ -0,0 +1,49 @@ +var BUGNUMBER = 1120169; +var summary = "Implement RegExp.prototype.{global, ignoreCase, multiline, sticky, unicode}"; + +print(BUGNUMBER + ": " + summary); + +var props = [ + "global", + "ignoreCase", + "multiline", + "sticky", + "unicode", +]; + +testThrows(RegExp.prototype); +test(/foo/iymg, [true, true, true, true, false]); +test(RegExp(""), [false, false, false, false, false]); +test(RegExp("", "mygi"), [true, true, true, true, false]); +test(RegExp("", "mygiu"), [true, true, true, true, true]); + +testThrowsGeneric(); +testThrowsGeneric(1); +testThrowsGeneric(""); +testThrowsGeneric({}); +testThrowsGeneric(new Proxy({}, {get(){ return true; }})); + +function test(obj, expects) { + for (var i = 0; i < props.length; i++) { + assertEq(obj[props[i]], expects[i]); + } +} + +function testThrows(obj) { + for (var prop of props) { + assertThrowsInstanceOf(obj[prop], TypeError); + } +} + +function testThrowsGeneric(obj) { + for (var prop of props) { + assertThrowsInstanceOf(() => genericGet(obj, prop), TypeError); + } +} + +function genericGet(obj, prop) { + return Object.getOwnPropertyDescriptor(RegExp.prototype, prop).get.call(obj); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/flags-param-handling.js b/js/src/tests/non262/RegExp/flags-param-handling.js new file mode 100644 index 0000000000..e47799601a --- /dev/null +++ b/js/src/tests/non262/RegExp/flags-param-handling.js @@ -0,0 +1,18 @@ +assertEq(RegExp(/foo/my).flags, "my"); +assertEq(RegExp(/foo/, "gi").flags, "gi"); +assertEq(RegExp(/foo/my, "gi").flags, "gi"); +assertEq(RegExp(/foo/my, "").flags, ""); +assertEq(RegExp(/foo/my, undefined).flags, "my"); +assertThrowsInstanceOf(() => RegExp(/foo/my, null), SyntaxError); +assertThrowsInstanceOf(() => RegExp(/foo/my, "foo"), SyntaxError); + +assertEq(/a/.compile("b", "gi").flags, "gi"); +assertEq(/a/.compile(/b/my).flags, "my"); +assertEq(/a/.compile(/b/my, undefined).flags, "my"); +assertThrowsInstanceOf(() => /a/.compile(/b/my, "gi"), TypeError); +assertThrowsInstanceOf(() => /a/.compile(/b/my, ""), TypeError); +assertThrowsInstanceOf(() => /a/.compile(/b/my, null), TypeError); +assertThrowsInstanceOf(() => /a/.compile(/b/my, "foo"), TypeError); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/flags.js b/js/src/tests/non262/RegExp/flags.js new file mode 100644 index 0000000000..61c806e47f --- /dev/null +++ b/js/src/tests/non262/RegExp/flags.js @@ -0,0 +1,26 @@ +var BUGNUMBER = 1108467; +var summary = "Implement RegExp.prototype.flags"; + +print(BUGNUMBER + ": " + summary); + +assertEq(RegExp.prototype.flags, ""); +assertEq(/foo/iymg.flags, "gimy"); +assertEq(RegExp("").flags, ""); +assertEq(RegExp("", "mygi").flags, "gimy"); +assertEq(RegExp("", "mygui").flags, "gimuy"); +assertEq(genericFlags({}), ""); +assertEq(genericFlags({ignoreCase: true}), "i"); +assertEq(genericFlags({sticky:1, unicode:1, global: 0}), "uy"); +assertEq(genericFlags({__proto__: {multiline: true}}), "m"); +assertEq(genericFlags(new Proxy({}, {get(){return true}})), "dgimsuvy"); + +assertThrowsInstanceOf(() => genericFlags(), TypeError); +assertThrowsInstanceOf(() => genericFlags(1), TypeError); +assertThrowsInstanceOf(() => genericFlags(""), TypeError); + +function genericFlags(obj) { + return Object.getOwnPropertyDescriptor(RegExp.prototype,"flags").get.call(obj); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/getter-name.js b/js/src/tests/non262/RegExp/getter-name.js new file mode 100644 index 0000000000..d0a413dbc4 --- /dev/null +++ b/js/src/tests/non262/RegExp/getter-name.js @@ -0,0 +1,16 @@ +var BUGNUMBER = 1180290; +var summary = 'RegExp getters should have get prefix'; + +print(BUGNUMBER + ": " + summary); + +assertEq(Object.getOwnPropertyDescriptor(RegExp, Symbol.species).get.name, "get [Symbol.species]"); +assertEq(Object.getOwnPropertyDescriptor(RegExp.prototype, "flags").get.name, "get flags"); +assertEq(Object.getOwnPropertyDescriptor(RegExp.prototype, "global").get.name, "get global"); +assertEq(Object.getOwnPropertyDescriptor(RegExp.prototype, "ignoreCase").get.name, "get ignoreCase"); +assertEq(Object.getOwnPropertyDescriptor(RegExp.prototype, "multiline").get.name, "get multiline"); +assertEq(Object.getOwnPropertyDescriptor(RegExp.prototype, "source").get.name, "get source"); +assertEq(Object.getOwnPropertyDescriptor(RegExp.prototype, "sticky").get.name, "get sticky"); +assertEq(Object.getOwnPropertyDescriptor(RegExp.prototype, "unicode").get.name, "get unicode"); + +if (typeof reportCompare === 'function') + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/ignoreCase-multiple.js b/js/src/tests/non262/RegExp/ignoreCase-multiple.js new file mode 100644 index 0000000000..e52cf499b3 --- /dev/null +++ b/js/src/tests/non262/RegExp/ignoreCase-multiple.js @@ -0,0 +1,71 @@ +var BUGNUMBER = 1280046; +var summary = "ignoreCase match should perform Canonicalize both on input and pattern."; + +print(BUGNUMBER + ": " + summary); + +// Each element [code1, upper, code2] satisfies the following condition: +// ToUpperCase(code1) == upper +// ToUpperCase(code2) == upper +var pairs = + [ + // U+00B5: MICRO SIGN + // U+039C: GREEK CAPITAL LETTER MU + // U+03BC: GREEK SMALL LETTER MU + ["\u00B5", "\u039C", "\u03BC"], + // U+0345: COMBINING GREEK YPOGEGRAMMENI + // U+0399: GREEK CAPITAL LETTER IOTA + // U+03B9: GREEK SMALL LETTER IOTA + ["\u0345", "\u0399", "\u03B9"], + // U+03C2: GREEK SMALL LETTER FINAL SIGMA + // U+03A3: GREEK CAPITAL LETTER SIGMA + // U+03C3: GREEK SMALL LETTER SIGMA + ["\u03C2", "\u03A3", "\u03C3"], + // U+03D0: GREEK BETA SYMBOL + // U+0392: GREEK CAPITAL LETTER BETA + // U+03B2: GREEK SMALL LETTER BETA + ["\u03D0", "\u0392", "\u03B2"], + // U+03D1: GREEK THETA SYMBOL + // U+0398: GREEK CAPITAL LETTER THETA + // U+03B8: GREEK SMALL LETTER THETA + ["\u03D1", "\u0398", "\u03B8"], + // U+03D5: GREEK PHI SYMBOL + // U+03A6: GREEK CAPITAL LETTER PHI + // U+03C6: GREEK SMALL LETTER PHI + ["\u03D5", "\u03A6", "\u03C6"], + // U+03D6: GREEK PI SYMBOL + // U+03A0: GREEK CAPITAL LETTER PI + // U+03C0: GREEK SMALL LETTER PI + ["\u03D6", "\u03A0", "\u03C0"], + // U+03F0: GREEK KAPPA SYMBOL + // U+039A: GREEK CAPITAL LETTER KAPPA + // U+03BA: GREEK SMALL LETTER KAPPA + ["\u03F0", "\u039A", "\u03BA"], + // U+03F1: GREEK RHO SYMBOL + // U+03A1: GREEK CAPITAL LETTER RHO + // U+03C1: GREEK SMALL LETTER RHO + ["\u03F1", "\u03A1", "\u03C1"], + // U+03F5: GREEK LUNATE EPSILON SYMBOL + // U+0395: GREEK CAPITAL LETTER EPSILON + // U+03B5: GREEK SMALL LETTER EPSILON + ["\u03F5", "\u0395", "\u03B5"], + // U+1E9B: LATIN SMALL LETTER LONG S WITH DOT ABOVE + // U+1E60: LATIN CAPITAL LETTER S WITH DOT ABOVE + // U+1E61: LATIN SMALL LETTER S WITH DOT ABOVE + ["\u1E9B", "\u1E60", "\u1E61"], + // U+1FBE: GREEK PROSGEGRAMMENI + // U+0399: GREEK CAPITAL LETTER IOTA + // U+03B9: GREEK SMALL LETTER IOTA + ["\u1FBE", "\u0399", "\u03B9"], + ]; + +for (var [code1, upper, code2] of pairs) { + assertEq(new RegExp(code1, "i").test(code2), true); + assertEq(new RegExp(code1, "i").test(upper), true); + assertEq(new RegExp(upper, "i").test(code1), true); + assertEq(new RegExp(upper, "i").test(code2), true); + assertEq(new RegExp(code2, "i").test(code1), true); + assertEq(new RegExp(code2, "i").test(upper), true); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/ignoreCase-non-latin1-to-latin1.js b/js/src/tests/non262/RegExp/ignoreCase-non-latin1-to-latin1.js new file mode 100644 index 0000000000..b534740454 --- /dev/null +++ b/js/src/tests/non262/RegExp/ignoreCase-non-latin1-to-latin1.js @@ -0,0 +1,118 @@ +var BUGNUMBER = 1338779; +var summary = "Non-Latin1 to Latin1 mapping in ignoreCase."; + +assertEq(/(\u039C)/.test("\xB5"), false); +assertEq(/(\u039C)+/.test("\xB5"), false); +assertEq(/(\u039C)/i.test("\xB5"), true); +assertEq(/(\u039C)+/i.test("\xB5"), true); +assertEq(/(\u039C)/u.test("\xB5"), false); +assertEq(/(\u039C)+/u.test("\xB5"), false); +assertEq(/(\u039C)/ui.test("\xB5"), true); +assertEq(/(\u039C)+/ui.test("\xB5"), true); + +assertEq(/(\xB5)/.test("\u039C"), false); +assertEq(/(\xB5)+/.test("\u039C"), false); +assertEq(/(\xB5)/i.test("\u039C"), true); +assertEq(/(\xB5)+/i.test("\u039C"), true); +assertEq(/(\xB5)/u.test("\u039C"), false); +assertEq(/(\xB5)+/u.test("\u039C"), false); +assertEq(/(\xB5)/ui.test("\u039C"), true); +assertEq(/(\xB5)+/ui.test("\u039C"), true); + + +assertEq(/(\u0178)/.test("\xFF"), false); +assertEq(/(\u0178)+/.test("\xFF"), false); +assertEq(/(\u0178)/i.test("\xFF"), true); +assertEq(/(\u0178)+/i.test("\xFF"), true); +assertEq(/(\u0178)/u.test("\xFF"), false); +assertEq(/(\u0178)+/u.test("\xFF"), false); +assertEq(/(\u0178)/ui.test("\xFF"), true); +assertEq(/(\u0178)+/ui.test("\xFF"), true); + +assertEq(/(\xFF)/.test("\u0178"), false); +assertEq(/(\xFF)+/.test("\u0178"), false); +assertEq(/(\xFF)/i.test("\u0178"), true); +assertEq(/(\xFF)+/i.test("\u0178"), true); +assertEq(/(\xFF)/u.test("\u0178"), false); +assertEq(/(\xFF)+/u.test("\u0178"), false); +assertEq(/(\xFF)/ui.test("\u0178"), true); +assertEq(/(\xFF)+/ui.test("\u0178"), true); + + +assertEq(/(\u017F)/.test("\x73"), false); +assertEq(/(\u017F)+/.test("\x73"), false); +assertEq(/(\u017F)/i.test("\x73"), false); +assertEq(/(\u017F)+/i.test("\x73"), false); +assertEq(/(\u017F)/u.test("\x73"), false); +assertEq(/(\u017F)+/u.test("\x73"), false); +assertEq(/(\u017F)/iu.test("\x73"), true); +assertEq(/(\u017F)+/iu.test("\x73"), true); + +assertEq(/(\x73)/.test("\u017F"), false); +assertEq(/(\x73)+/.test("\u017F"), false); +assertEq(/(\x73)/i.test("\u017F"), false); +assertEq(/(\x73)+/i.test("\u017F"), false); +assertEq(/(\x73)/u.test("\u017F"), false); +assertEq(/(\x73)+/u.test("\u017F"), false); +assertEq(/(\x73)/iu.test("\u017F"), true); +assertEq(/(\x73)+/iu.test("\u017F"), true); + + +assertEq(/(\u1E9E)/.test("\xDF"), false); +assertEq(/(\u1E9E)+/.test("\xDF"), false); +assertEq(/(\u1E9E)/i.test("\xDF"), false); +assertEq(/(\u1E9E)+/i.test("\xDF"), false); +assertEq(/(\u1E9E)/u.test("\xDF"), false); +assertEq(/(\u1E9E)+/u.test("\xDF"), false); +assertEq(/(\u1E9E)/iu.test("\xDF"), true); +assertEq(/(\u1E9E)+/iu.test("\xDF"), true); + +assertEq(/(\xDF)/.test("\u1E9E"), false); +assertEq(/(\xDF)+/.test("\u1E9E"), false); +assertEq(/(\xDF)/i.test("\u1E9E"), false); +assertEq(/(\xDF)+/i.test("\u1E9E"), false); +assertEq(/(\xDF)/u.test("\u1E9E"), false); +assertEq(/(\xDF)+/u.test("\u1E9E"), false); +assertEq(/(\xDF)/iu.test("\u1E9E"), true); +assertEq(/(\xDF)+/iu.test("\u1E9E"), true); + + +assertEq(/(\u212A)/.test("\x6B"), false); +assertEq(/(\u212A)+/.test("\x6B"), false); +assertEq(/(\u212A)/i.test("\x6B"), false); +assertEq(/(\u212A)+/i.test("\x6B"), false); +assertEq(/(\u212A)/u.test("\x6B"), false); +assertEq(/(\u212A)+/u.test("\x6B"), false); +assertEq(/(\u212A)/iu.test("\x6B"), true); +assertEq(/(\u212A)+/iu.test("\x6B"), true); + +assertEq(/(\x6B)/.test("\u212A"), false); +assertEq(/(\x6B)+/.test("\u212A"), false); +assertEq(/(\x6B)/i.test("\u212A"), false); +assertEq(/(\x6B)+/i.test("\u212A"), false); +assertEq(/(\x6B)/u.test("\u212A"), false); +assertEq(/(\x6B)+/u.test("\u212A"), false); +assertEq(/(\x6B)/iu.test("\u212A"), true); +assertEq(/(\x6B)+/iu.test("\u212A"), true); + + +assertEq(/(\u212B)/.test("\xE5"), false); +assertEq(/(\u212B)+/.test("\xE5"), false); +assertEq(/(\u212B)/i.test("\xE5"), false); +assertEq(/(\u212B)+/i.test("\xE5"), false); +assertEq(/(\u212B)/u.test("\xE5"), false); +assertEq(/(\u212B)+/u.test("\xE5"), false); +assertEq(/(\u212B)/iu.test("\xE5"), true); +assertEq(/(\u212B)+/iu.test("\xE5"), true); + +assertEq(/(\xE5)/.test("\u212B"), false); +assertEq(/(\xE5)+/.test("\u212B"), false); +assertEq(/(\xE5)/i.test("\u212B"), false); +assertEq(/(\xE5)+/i.test("\u212B"), false); +assertEq(/(\xE5)/u.test("\u212B"), false); +assertEq(/(\xE5)+/u.test("\u212B"), false); +assertEq(/(\xE5)/iu.test("\u212B"), true); +assertEq(/(\xE5)+/iu.test("\u212B"), true); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/instance-property-storage-introspection.js b/js/src/tests/non262/RegExp/instance-property-storage-introspection.js new file mode 100644 index 0000000000..998d25e2c0 --- /dev/null +++ b/js/src/tests/non262/RegExp/instance-property-storage-introspection.js @@ -0,0 +1,128 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 640072; +var summary = + "Represent /a/.{lastIndex,global,source,multiline,sticky,ignoreCase} with " + + "plain old data properties"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function checkDataProperty(obj, p, expect, msg) +{ + var d = Object.getOwnPropertyDescriptor(obj, p); + + assertEq(d.value, expect.value, msg + ": bad value for " + p); + assertEq(d.writable, expect.writable, msg + ": bad writable for " + p); + assertEq(d.enumerable, expect.enumerable, msg + ": bad enumerable for " + p); + assertEq(d.configurable, expect.configurable, msg + ": bad configurable for " + p); + + // Try redefining the property using its initial values: these should all be + // silent no-ops. + Object.defineProperty(obj, p, { value: expect.value }); + Object.defineProperty(obj, p, { writable: expect.writable }); + Object.defineProperty(obj, p, { enumerable: expect.enumerable }); + Object.defineProperty(obj, p, { configurable: expect.configurable }); + + var d2 = Object.getOwnPropertyDescriptor(obj, p); + assertEq(d.value, d2.value, msg + ": value changed on redefinition of " + p + "?"); + assertEq(d.writable, d2.writable, msg + ": writable changed on redefinition of " + p + "?"); + assertEq(d.enumerable, d2.enumerable, msg + ": enumerable changed on redefinition of " + p + "?"); + assertEq(d.configurable, d2.configurable, msg + ": configurable changed on redefinition of " + p + "?"); +} + + +// Check a bunch of "empty" regular expressions first. + +var choices = [{ msg: "new RegExp()", + get: function() { return new RegExp(); } }, + { msg: "/(?:)/", + get: Function("return /(?:)/;") }]; + +function checkRegExp(r, msg, lastIndex) +{ + var expect; + + expect = { value: lastIndex, enumerable: false, configurable: false, writable: true }; + checkDataProperty(r, "lastIndex", expect, msg); +} + +checkRegExp(new RegExp(), "new RegExp()", 0); +checkRegExp(/(?:)/, "/(?:)/", 0); +checkRegExp(Function("return /(?:)/;")(), 'Function("return /(?:)/;")()', 0); + +for (var i = 0; i < choices.length; i++) +{ + var choice = choices[i]; + var msg = choice.msg; + var r = choice.get(); + + checkRegExp(r, msg, 0); +} + +// Now test less generic regular expressions + +checkRegExp(/a/gim, "/a/gim", 0); + +var r; + +do +{ + r = /abcd/mg; + checkRegExp(r, "/abcd/mg initially", 0); + r.exec("abcdefg"); + checkRegExp(r, "/abcd/mg step 1", 4); + r.exec("abcdabcd"); + checkRegExp(r, "/abcd/mg step 2", 8); + r.exec("abcdabcd"); + checkRegExp(r, "/abcd/mg end", 0); + + r = /cde/ig; + checkRegExp(r, "/cde/ig initially", 0); + var obj = r.lastIndex = { valueOf: function() { return 2; } }; + checkRegExp(r, "/cde/ig after lastIndex", obj); + r.exec("aaacdef"); + checkRegExp(r, "/cde/ig after exec", 6); + Object.defineProperty(r, "lastIndex", { value: 3 }); + checkRegExp(r, "/cde/ig after define 3", 3); + Object.defineProperty(r, "lastIndex", { value: obj }); + checkRegExp(r, "/cde/ig after lastIndex", obj); + + + // Tricky bits of testing: make sure that redefining lastIndex doesn't change + // the slot where the lastIndex property is initially stored, even if + // the redefinition also changes writability. + r = /a/g; + checkRegExp(r, "/a/g initially", 0); + Object.defineProperty(r, "lastIndex", { value: 2 }); + r.exec("aabbbba"); + checkRegExp(r, "/a/g after first exec", 7); + assertEq(r.lastIndex, 7); + r.lastIndex = 2; + checkRegExp(r, "/a/g after assign", 2); + r.exec("aabbbba"); + assertEq(r.lastIndex, 7); // check in reverse order + checkRegExp(r, "/a/g after second exec", 7); + + r = /c/g; + r.lastIndex = 2; + checkRegExp(r, "/c/g initially", 2); + Object.defineProperty(r, "lastIndex", { writable: false }); + assertEq(Object.getOwnPropertyDescriptor(r, "lastIndex").writable, false); + try { r.exec("aabbbba"); } catch (e) { /* swallow error if thrown */ } + assertEq(Object.getOwnPropertyDescriptor(r, "lastIndex").writable, false); +} +while (Math.random() > 17); // fake loop to discourage RegExp object caching + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/RegExp/lastIndex-exec.js b/js/src/tests/non262/RegExp/lastIndex-exec.js new file mode 100644 index 0000000000..f42facbe34 --- /dev/null +++ b/js/src/tests/non262/RegExp/lastIndex-exec.js @@ -0,0 +1,80 @@ +// RegExp.prototype.exec: Test lastIndex changes for ES2017. + +// Test various combinations of: +// - Pattern matches or doesn't match +// - Global and/or sticky flag is set. +// - lastIndex exceeds the input string length +// - lastIndex is +-0 +const testCases = [ + { regExp: /a/, lastIndex: 0, input: "a", result: 0 }, + { regExp: /a/g, lastIndex: 0, input: "a", result: 1 }, + { regExp: /a/y, lastIndex: 0, input: "a", result: 1 }, + + { regExp: /a/, lastIndex: 0, input: "b", result: 0 }, + { regExp: /a/g, lastIndex: 0, input: "b", result: 0 }, + { regExp: /a/y, lastIndex: 0, input: "b", result: 0 }, + + { regExp: /a/, lastIndex: -0, input: "a", result: -0 }, + { regExp: /a/g, lastIndex: -0, input: "a", result: 1 }, + { regExp: /a/y, lastIndex: -0, input: "a", result: 1 }, + + { regExp: /a/, lastIndex: -0, input: "b", result: -0 }, + { regExp: /a/g, lastIndex: -0, input: "b", result: 0 }, + { regExp: /a/y, lastIndex: -0, input: "b", result: 0 }, + + { regExp: /a/, lastIndex: -1, input: "a", result: -1 }, + { regExp: /a/g, lastIndex: -1, input: "a", result: 1 }, + { regExp: /a/y, lastIndex: -1, input: "a", result: 1 }, + + { regExp: /a/, lastIndex: -1, input: "b", result: -1 }, + { regExp: /a/g, lastIndex: -1, input: "b", result: 0 }, + { regExp: /a/y, lastIndex: -1, input: "b", result: 0 }, + + { regExp: /a/, lastIndex: 100, input: "a", result: 100 }, + { regExp: /a/g, lastIndex: 100, input: "a", result: 0 }, + { regExp: /a/y, lastIndex: 100, input: "a", result: 0 }, +]; + +// Basic test. +for (let {regExp, lastIndex, input, result} of testCases) { + let re = new RegExp(regExp); + re.lastIndex = lastIndex; + re.exec(input); + assertEq(re.lastIndex, result); +} + +// Test when lastIndex is non-writable. +for (let {regExp, lastIndex, input} of testCases) { + let re = new RegExp(regExp); + Object.defineProperty(re, "lastIndex", { value: lastIndex, writable: false }); + if (re.global || re.sticky) { + assertThrowsInstanceOf(() => re.exec(input), TypeError); + } else { + re.exec(input); + } + assertEq(re.lastIndex, lastIndex); +} + +// Test when lastIndex is changed to non-writable as a side-effect. +for (let {regExp, lastIndex, input} of testCases) { + let re = new RegExp(regExp); + let called = false; + re.lastIndex = { + valueOf() { + assertEq(called, false); + called = true; + Object.defineProperty(re, "lastIndex", { value: 9000, writable: false }); + return lastIndex; + } + }; + if (re.global || re.sticky) { + assertThrowsInstanceOf(() => re.exec(input), TypeError); + } else { + re.exec(input); + } + assertEq(re.lastIndex, 9000); + assertEq(called, true); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/lastIndex-match-or-replace.js b/js/src/tests/non262/RegExp/lastIndex-match-or-replace.js new file mode 100644 index 0000000000..8d7703c459 --- /dev/null +++ b/js/src/tests/non262/RegExp/lastIndex-match-or-replace.js @@ -0,0 +1,123 @@ +// RegExp.prototype[Symbol.match, Symbol.replace]: Test lastIndex changes for ES2017. + +// RegExp-like class to test the RegExp method slow paths. +class DuckRegExp extends RegExp { + constructor(pattern, flags) { + return Object.create(DuckRegExp.prototype, { + regExp: { + value: new RegExp(pattern, flags) + }, + lastIndex: { + value: 0, writable: true, enumerable: false, configurable: false + } + }); + } + + exec(...args) { + this.regExp.lastIndex = this.lastIndex; + try { + return this.regExp.exec(...args); + } finally { + if (this.global || this.sticky) + this.lastIndex = this.regExp.lastIndex; + } + } + + get source() { return this.regExp.source; } + + get flags() { return this.regExp.flags; } + get global() { return this.regExp.global; } + get ignoreCase() { return this.regExp.ignoreCase; } + get multiline() { return this.regExp.multiline; } + get sticky() { return this.regExp.sticky; } + get unicode() { return this.regExp.unicode; } +} + +// Test various combinations of: +// - Pattern matches or doesn't match +// - Global and/or sticky flag is set. +// - lastIndex exceeds the input string length +// - lastIndex is +-0 +const testCases = [ + { regExp: /a/, lastIndex: 0, input: "a", result: 0 }, + { regExp: /a/g, lastIndex: 0, input: "a", result: 0 }, + { regExp: /a/y, lastIndex: 0, input: "a", result: 1 }, + + { regExp: /a/, lastIndex: 0, input: "b", result: 0 }, + { regExp: /a/g, lastIndex: 0, input: "b", result: 0 }, + { regExp: /a/y, lastIndex: 0, input: "b", result: 0 }, + + { regExp: /a/, lastIndex: -0, input: "a", result: -0 }, + { regExp: /a/g, lastIndex: -0, input: "a", result: 0 }, + { regExp: /a/y, lastIndex: -0, input: "a", result: 1 }, + + { regExp: /a/, lastIndex: -0, input: "b", result: -0 }, + { regExp: /a/g, lastIndex: -0, input: "b", result: 0 }, + { regExp: /a/y, lastIndex: -0, input: "b", result: 0 }, + + { regExp: /a/, lastIndex: -1, input: "a", result: -1 }, + { regExp: /a/g, lastIndex: -1, input: "a", result: 0 }, + { regExp: /a/y, lastIndex: -1, input: "a", result: 1 }, + + { regExp: /a/, lastIndex: -1, input: "b", result: -1 }, + { regExp: /a/g, lastIndex: -1, input: "b", result: 0 }, + { regExp: /a/y, lastIndex: -1, input: "b", result: 0 }, + + { regExp: /a/, lastIndex: 100, input: "a", result: 100 }, + { regExp: /a/g, lastIndex: 100, input: "a", result: 0 }, + { regExp: /a/y, lastIndex: 100, input: "a", result: 0 }, +]; + +for (let method of [RegExp.prototype[Symbol.match], RegExp.prototype[Symbol.replace]]) { + for (let Constructor of [RegExp, DuckRegExp]) { + // Basic test. + for (let {regExp, lastIndex, input, result} of testCases) { + let re = new Constructor(regExp); + re.lastIndex = lastIndex; + Reflect.apply(method, re, [input]); + assertEq(re.lastIndex, result); + } + + // Test when lastIndex is non-writable. + for (let {regExp, lastIndex, input} of testCases) { + let re = new Constructor(regExp); + Object.defineProperty(re, "lastIndex", { value: lastIndex, writable: false }); + if (re.global || re.sticky) { + assertThrowsInstanceOf(() => Reflect.apply(method, re, [input]), TypeError); + } else { + Reflect.apply(method, re, [input]); + } + assertEq(re.lastIndex, lastIndex); + } + + // Test when lastIndex is changed to non-writable as a side-effect. + for (let {regExp, lastIndex, input, result} of testCases) { + let re = new Constructor(regExp); + let called = false; + re.lastIndex = { + valueOf() { + assertEq(called, false); + called = true; + Object.defineProperty(re, "lastIndex", { value: 9000, writable: false }); + return lastIndex; + } + }; + if (re.sticky) { + assertThrowsInstanceOf(() => Reflect.apply(method, re, [input]), TypeError); + assertEq(called, true); + assertEq(re.lastIndex, 9000); + } else if (re.global) { + Reflect.apply(method, re, [input]); + assertEq(called, false); + assertEq(re.lastIndex, result); + } else { + Reflect.apply(method, re, [input]); + assertEq(called, true); + assertEq(re.lastIndex, 9000); + } + } + } +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/lastIndex-nonwritable.js b/js/src/tests/non262/RegExp/lastIndex-nonwritable.js new file mode 100644 index 0000000000..3c867f9538 --- /dev/null +++ b/js/src/tests/non262/RegExp/lastIndex-nonwritable.js @@ -0,0 +1,27 @@ +var BUGNUMBER = 1168416; +var summary = "Regexp.prototype.test/exec shouldn't change lastIndex if not writable."; + +print(BUGNUMBER + ": " + summary); + +var regex = /0/g; +Object.freeze(regex); +var str = "abc000"; + +var desc = Object.getOwnPropertyDescriptor(regex, "lastIndex"); +assertEq(desc.writable, false); +assertEq(desc.value, 0); + +assertThrowsInstanceOf(() => regex.test(str), TypeError); + +desc = Object.getOwnPropertyDescriptor(regex, "lastIndex"); +assertEq(desc.writable, false); +assertEq(desc.value, 0); + +assertThrowsInstanceOf(() => regex.exec(str), TypeError); + +desc = Object.getOwnPropertyDescriptor(regex, "lastIndex"); +assertEq(desc.writable, false); +assertEq(desc.value, 0); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/lastIndex-search.js b/js/src/tests/non262/RegExp/lastIndex-search.js new file mode 100644 index 0000000000..5953b3a885 --- /dev/null +++ b/js/src/tests/non262/RegExp/lastIndex-search.js @@ -0,0 +1,118 @@ +// RegExp.prototype[Symbol.search]: Test lastIndex changes for ES2017. + +// RegExp-like class to test the RegExp method slow paths. +class DuckRegExp extends RegExp { + constructor(pattern, flags) { + return Object.create(DuckRegExp.prototype, { + regExp: { + value: new RegExp(pattern, flags) + }, + lastIndex: { + value: 0, writable: true, enumerable: false, configurable: false + } + }); + } + + exec(...args) { + this.regExp.lastIndex = this.lastIndex; + try { + return this.regExp.exec(...args); + } finally { + if (this.global || this.sticky) + this.lastIndex = this.regExp.lastIndex; + } + } + + get source() { return this.regExp.source; } + + get global() { return this.regExp.global; } + get ignoreCase() { return this.regExp.ignoreCase; } + get multiline() { return this.regExp.multiline; } + get sticky() { return this.regExp.sticky; } + get unicode() { return this.regExp.unicode; } +} + +// Test various combinations of: +// - Pattern matches or doesn't match +// - Global and/or sticky flag is set. +// - lastIndex exceeds the input string length +// - lastIndex is +-0 +const testCasesNotPositiveZero = [ + { regExp: /a/, lastIndex: -1, input: "a" }, + { regExp: /a/g, lastIndex: -1, input: "a" }, + { regExp: /a/y, lastIndex: -1, input: "a" }, + + { regExp: /a/, lastIndex: 100, input: "a" }, + { regExp: /a/g, lastIndex: 100, input: "a" }, + { regExp: /a/y, lastIndex: 100, input: "a" }, + + { regExp: /a/, lastIndex: -1, input: "b" }, + { regExp: /a/g, lastIndex: -1, input: "b" }, + { regExp: /a/y, lastIndex: -1, input: "b" }, + + { regExp: /a/, lastIndex: -0, input: "a" }, + { regExp: /a/g, lastIndex: -0, input: "a" }, + { regExp: /a/y, lastIndex: -0, input: "a" }, + + { regExp: /a/, lastIndex: -0, input: "b" }, + { regExp: /a/g, lastIndex: -0, input: "b" }, + { regExp: /a/y, lastIndex: -0, input: "b" }, +]; + +const testCasesPositiveZero = [ + { regExp: /a/, lastIndex: 0, input: "a" }, + { regExp: /a/g, lastIndex: 0, input: "a" }, + { regExp: /a/y, lastIndex: 0, input: "a" }, + + { regExp: /a/, lastIndex: 0, input: "b" }, + { regExp: /a/g, lastIndex: 0, input: "b" }, + { regExp: /a/y, lastIndex: 0, input: "b" }, +]; + +const testCases = [...testCasesNotPositiveZero, ...testCasesPositiveZero]; + +for (let Constructor of [RegExp, DuckRegExp]) { + // Basic test. + for (let {regExp, lastIndex, input} of testCases) { + let re = new Constructor(regExp); + re.lastIndex = lastIndex; + re[Symbol.search](input); + assertEq(re.lastIndex, lastIndex); + } + + // Test when lastIndex is non-writable and not positive zero. + for (let {regExp, lastIndex, input} of testCasesNotPositiveZero) { + let re = new Constructor(regExp); + Object.defineProperty(re, "lastIndex", { value: lastIndex, writable: false }); + assertThrowsInstanceOf(() => re[Symbol.search](input), TypeError); + assertEq(re.lastIndex, lastIndex); + } + + // Test when lastIndex is non-writable and positive zero. + for (let {regExp, lastIndex, input} of testCasesPositiveZero) { + let re = new Constructor(regExp); + Object.defineProperty(re, "lastIndex", { value: lastIndex, writable: false }); + if (re.global || re.sticky) { + assertThrowsInstanceOf(() => re[Symbol.search](input), TypeError); + } else { + re[Symbol.search](input); + } + assertEq(re.lastIndex, lastIndex); + } + + // Test lastIndex isn't converted to a number. + for (let {regExp, lastIndex, input} of testCases) { + let re = new RegExp(regExp); + let badIndex = { + valueOf() { + assertEq(false, true); + } + }; + re.lastIndex = badIndex; + re[Symbol.search](input); + assertEq(re.lastIndex, badIndex); + } +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/match-local-tolength-recompilation.js b/js/src/tests/non262/RegExp/match-local-tolength-recompilation.js new file mode 100644 index 0000000000..9a992f81f4 --- /dev/null +++ b/js/src/tests/non262/RegExp/match-local-tolength-recompilation.js @@ -0,0 +1,75 @@ +// Side-effects when calling ToLength(regExp.lastIndex) in +// RegExp.prototype[@@match] for non-global RegExp can recompile the RegExp. + +for (var flag of ["", "y"]) { + var regExp = new RegExp("a", flag); + + regExp.lastIndex = { + valueOf() { + regExp.compile("b"); + return 0; + } + }; + + var result = regExp[Symbol.match]("b"); + assertEq(result !== null, true); +} + +// Recompilation modifies flag: +// Case 1: Adds global flag, validate by checking lastIndex. +var regExp = new RegExp("a", ""); +regExp.lastIndex = { + valueOf() { + // |regExp| is now in global mode, RegExpBuiltinExec should update the + // lastIndex property to reflect last match. + regExp.compile("a", "g"); + return 0; + } +}; +regExp[Symbol.match]("a"); +assertEq(regExp.lastIndex, 1); + +// Case 2: Removes sticky flag with match, validate by checking lastIndex. +var regExp = new RegExp("a", "y"); +regExp.lastIndex = { + valueOf() { + // |regExp| is no longer sticky, RegExpBuiltinExec shouldn't modify the + // lastIndex property. + regExp.compile("a", ""); + regExp.lastIndex = 9000; + return 0; + } +}; +regExp[Symbol.match]("a"); +assertEq(regExp.lastIndex, 9000); + +// Case 3.a: Removes sticky flag without match, validate by checking lastIndex. +var regExp = new RegExp("a", "y"); +regExp.lastIndex = { + valueOf() { + // |regExp| is no longer sticky, RegExpBuiltinExec shouldn't modify the + // lastIndex property. + regExp.compile("b", ""); + regExp.lastIndex = 9001; + return 0; + } +}; +regExp[Symbol.match]("a"); +assertEq(regExp.lastIndex, 9001); + +// Case 3.b: Removes sticky flag without match, validate by checking lastIndex. +var regExp = new RegExp("a", "y"); +regExp.lastIndex = { + valueOf() { + // |regExp| is no longer sticky, RegExpBuiltinExec shouldn't modify the + // lastIndex property. + regExp.compile("b", ""); + regExp.lastIndex = 9002; + return 10000; + } +}; +regExp[Symbol.match]("a"); +assertEq(regExp.lastIndex, 9002); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/match-this.js b/js/src/tests/non262/RegExp/match-this.js new file mode 100644 index 0000000000..ee05462f26 --- /dev/null +++ b/js/src/tests/non262/RegExp/match-this.js @@ -0,0 +1,12 @@ +var BUGNUMBER = 887016; +var summary = "RegExp.prototype[@@match] should check this value."; + +print(BUGNUMBER + ": " + summary); + +for (var v of [null, 1, true, undefined, "", Symbol.iterator]) { + assertThrowsInstanceOf(() => RegExp.prototype[Symbol.match].call(v), + TypeError); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/match-trace.js b/js/src/tests/non262/RegExp/match-trace.js new file mode 100644 index 0000000000..507d3f661a --- /dev/null +++ b/js/src/tests/non262/RegExp/match-trace.js @@ -0,0 +1,142 @@ +var BUGNUMBER = 887016; +var summary = "Trace RegExp.prototype[@@match] behavior."; + +print(BUGNUMBER + ": " + summary); + +var n; +var log; +var target; +var global; +var unicode; +var logProxy; + +var execResult; +var lastIndexResult; +var lastIndexExpected; + +function P(A) { + return new Proxy(A, { + get(that, name) { + if (logProxy) + log += "get:result[" + name + "],"; + return that[name]; + } + }); +} + +var myRegExp = { + get flags() { + log += "get:flags,"; + var flags = ""; + if (global) flags += "g"; + if (unicode) flags += "u"; + return flags; + }, + get lastIndex() { + log += "get:lastIndex,"; + return lastIndexResult[n]; + }, + set lastIndex(v) { + log += "set:lastIndex,"; + assertEq(v, lastIndexExpected[n]); + }, + get exec() { + log += "get:exec,"; + return function(S) { + log += "call:exec,"; + assertEq(S, target); + return execResult[n++]; + }; + }, +}; + +function reset() { + n = 0; + log = ""; + target = "abcAbcABC"; + global = true; + unicode = false; + logProxy = true; +} + +// Trace global with non-empty match. +reset(); +execResult = [ P(["abc"]), P(["ABC"]), null ]; +lastIndexResult = [ , , , ]; +lastIndexExpected = [ 0, , , ]; +var ret = RegExp.prototype[Symbol.match].call(myRegExp, target); +assertEq(JSON.stringify(ret), `["abc","ABC"]`); +assertEq(log, + "get:flags," + + "set:lastIndex," + + "get:exec,call:exec,get:result[0]," + + "get:exec,call:exec,get:result[0]," + + "get:exec,call:exec,"); + +// Trace global with empty match. +reset(); +execResult = [ P([""]), P([""]), null ]; +lastIndexResult = [ , 4, 20, ]; +lastIndexExpected = [ 0, 5, 21, ]; +ret = RegExp.prototype[Symbol.match].call(myRegExp, target); +assertEq(JSON.stringify(ret), `["",""]`); +assertEq(log, + "get:flags," + + "set:lastIndex," + + "get:exec,call:exec,get:result[0],get:lastIndex,set:lastIndex," + + "get:exec,call:exec,get:result[0],get:lastIndex,set:lastIndex," + + "get:exec,call:exec,"); + +// Trace global and unicode with empty match. +// 1. not surrogate pair +// 2. lead surrogate pair +// 3. trail surrogate pair +// 4. lead surrogate pair without trail surrogate pair +// 5. index overflow +reset(); +unicode = true; +// 0123 4 5678 +target = "___\uD83D\uDC38___\uD83D"; +execResult = [ P([""]), P([""]), P([""]), P([""]), P([""]), null ]; +lastIndexResult = [ , 2, 3, 4, 8, 9, ]; +lastIndexExpected = [ 0, 3, 5, 5, 9, 10, ]; +ret = RegExp.prototype[Symbol.match].call(myRegExp, target); +assertEq(JSON.stringify(ret), `["","","","",""]`); +assertEq(log, + "get:flags," + + "set:lastIndex," + + "get:exec,call:exec,get:result[0],get:lastIndex,set:lastIndex," + + "get:exec,call:exec,get:result[0],get:lastIndex,set:lastIndex," + + "get:exec,call:exec,get:result[0],get:lastIndex,set:lastIndex," + + "get:exec,call:exec,get:result[0],get:lastIndex,set:lastIndex," + + "get:exec,call:exec,get:result[0],get:lastIndex,set:lastIndex," + + "get:exec,call:exec,"); + +// Trace global with no match. +reset(); +execResult = [ null ]; +lastIndexResult = [ , ]; +lastIndexExpected = [ 0, ]; +ret = RegExp.prototype[Symbol.match].call(myRegExp, target); +assertEq(ret, null); +assertEq(log, + "get:flags," + + "set:lastIndex," + + "get:exec,call:exec,"); + +// Trace non-global. +reset(); +global = false; +execResult = [ P(["abc"]) ]; +lastIndexResult = []; +lastIndexExpected = []; +ret = RegExp.prototype[Symbol.match].call(myRegExp, target); +// ret is the Proxy on non-global case, disable logging. +logProxy = false; +assertEq(JSON.stringify(ret), `["abc"]`); +assertEq(log, + "get:flags," + + "get:exec,call:exec,"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/match.js b/js/src/tests/non262/RegExp/match.js new file mode 100644 index 0000000000..06308b2d67 --- /dev/null +++ b/js/src/tests/non262/RegExp/match.js @@ -0,0 +1,36 @@ +var BUGNUMBER = 887016; +var summary = "Implement RegExp.prototype[@@match]."; + +print(BUGNUMBER + ": " + summary); + +assertEq(RegExp.prototype[Symbol.match].name, "[Symbol.match]"); +assertEq(RegExp.prototype[Symbol.match].length, 1); +var desc = Object.getOwnPropertyDescriptor(RegExp.prototype, Symbol.match); +assertEq(desc.configurable, true); +assertEq(desc.enumerable, false); +assertEq(desc.writable, true); + +var re = /a/; +var v = re[Symbol.match]("abcAbcABC"); +assertEq(Array.isArray(v), true); +assertEq(v.length, 1); +assertEq(v[0], "a"); + +re = /d/; +v = re[Symbol.match]("abcAbcABC"); +assertEq(v, null); + +re = /a/ig; +v = re[Symbol.match]("abcAbcABC"); +assertEq(Array.isArray(v), true); +assertEq(v.length, 3); +assertEq(v[0], "a"); +assertEq(v[1], "A"); +assertEq(v[2], "A"); + +re = /d/g; +v = re[Symbol.match]("abcAbcABC"); +assertEq(v, null); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/multiline-001.js b/js/src/tests/non262/RegExp/multiline-001.js new file mode 100644 index 0000000000..43614d91e7 --- /dev/null +++ b/js/src/tests/non262/RegExp/multiline-001.js @@ -0,0 +1,67 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + * File Name: RegExp/multiline-001.js + * ECMA Section: + * Description: Based on ECMA 2 Draft 7 February 1999 + * + * Date: 19 February 1999 + */ + +var SECTION = "RegExp/multiline-001"; +var TITLE = "RegExp: multiline flag"; +var BUGNUMBER="343901"; + +printBugNumber(BUGNUMBER); + +var woodpeckers = "ivory-billed\ndowny\nhairy\nacorn\nyellow-bellied sapsucker\n" + + "northern flicker\npileated\n"; + +AddRegExpCases( /.*[y]$/m, woodpeckers, woodpeckers.indexOf("downy"), ["downy"] ); + +AddRegExpCases( /.*[d]$/m, woodpeckers, woodpeckers.indexOf("ivory-billed"), ["ivory-billed"] ); + +test(); + + +function AddRegExpCases +( regexp, pattern, index, matches_array ) { + + // prevent a runtime error + + if ( regexp.exec(pattern) == null || matches_array == null ) { + AddTestCase( + regexp + ".exec(" + pattern +")", + matches_array, + regexp.exec(pattern) ); + + return; + } + + AddTestCase( + regexp.toString() + ".exec(" + pattern +").length", + matches_array.length, + regexp.exec(pattern).length ); + + AddTestCase( + regexp.toString() + ".exec(" + pattern +").index", + index, + regexp.exec(pattern).index ); + + AddTestCase( + regexp + ".exec(" + pattern +").input", + pattern, + regexp.exec(pattern).input ); + + + for ( var matches = 0; matches < matches_array.length; matches++ ) { + AddTestCase( + regexp + ".exec(" + pattern +")[" + matches +"]", + matches_array[matches], + regexp.exec(pattern)[matches] ); + } +} diff --git a/js/src/tests/non262/RegExp/octal-001.js b/js/src/tests/non262/RegExp/octal-001.js new file mode 100644 index 0000000000..cde12d807d --- /dev/null +++ b/js/src/tests/non262/RegExp/octal-001.js @@ -0,0 +1,77 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + * File Name: RegExp/octal-001.js + * ECMA Section: 15.7.1 + * Description: Based on ECMA 2 Draft 7 February 1999 + * Simple test cases for matching OctalEscapeSequences. + * Author: christine@netscape.com + * Date: 19 February 1999 + */ +var SECTION = "RegExp/octal-001.js"; +var TITLE = "RegExp patterns that contain OctalEscapeSequences"; +var BUGNUMBER="http://scopus/bugsplat/show_bug.cgi?id=346196"; + +printBugNumber(BUGNUMBER); + + +// backreference +AddRegExpCases( + /(.)\1/, + "/(.)\\1/", + "HI!!", + "HI!", + 2, + ["!!", "!"] ); + +test(); + +function AddRegExpCases( + regexp, str_regexp, pattern, str_pattern, index, matches_array ) { + + // prevent a runtime error + + if ( regexp.exec(pattern) == null || matches_array == null ) { + AddTestCase( + regexp + ".exec(" + str_pattern +")", + matches_array, + regexp.exec(pattern) ); + + return; + } + AddTestCase( + str_regexp + ".exec(" + str_pattern +").length", + matches_array.length, + regexp.exec(pattern).length ); + + AddTestCase( + str_regexp + ".exec(" + str_pattern +").index", + index, + regexp.exec(pattern).index ); + + AddTestCase( + str_regexp + ".exec(" + str_pattern +").input", + pattern, + regexp.exec(pattern).input ); + + AddTestCase( + str_regexp + ".exec(" + str_pattern +").toString()", + matches_array.toString(), + regexp.exec(pattern).toString() ); +/* + var limit = matches_array.length > regexp.exec(pattern).length + ? matches_array.length + : regexp.exec(pattern).length; + + for ( var matches = 0; matches < limit; matches++ ) { + AddTestCase( + str_regexp + ".exec(" + str_pattern +")[" + matches +"]", + matches_array[matches], + regexp.exec(pattern)[matches] ); + } +*/ +} diff --git a/js/src/tests/non262/RegExp/octal-002.js b/js/src/tests/non262/RegExp/octal-002.js new file mode 100644 index 0000000000..6761d4ae6d --- /dev/null +++ b/js/src/tests/non262/RegExp/octal-002.js @@ -0,0 +1,92 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + * File Name: RegExp/octal-002.js + * ECMA Section: 15.7.1 + * Description: Based on ECMA 2 Draft 7 February 1999 + * Simple test cases for matching OctalEscapeSequences. + * Author: christine@netscape.com + * Date: 19 February 1999 + */ +var SECTION = "RegExp/octal-002.js"; +var TITLE = "RegExp patterns that contain OctalEscapeSequences"; +var BUGNUMBER="http://scopus/bugsplat/show_bug.cgi?id=346189"; + +printBugNumber(BUGNUMBER); + +// backreference +AddRegExpCases( + /(.)(.)(.)(.)(.)(.)(.)(.)\8/, + "/(.)(.)(.)(.)(.)(.)(.)(.)\\8", + "aabbccaaabbbccc", + "aabbccaaabbbccc", + 0, + ["aabbccaaa", "a", "a", "b", "b", "c", "c", "a", "a"] ); + +AddRegExpCases( + /(.)(.)(.)(.)(.)(.)(.)(.)(.)\9/, + "/(.)(.)(.)(.)(.)(.)(.)(.)\\9", + "aabbccaabbcc", + "aabbccaabbcc", + 0, + ["aabbccaabb", "a", "a", "b", "b", "c", "c", "a", "a", "b"] ); + +AddRegExpCases( + /(.)(.)(.)(.)(.)(.)(.)(.)(.)\8/, + "/(.)(.)(.)(.)(.)(.)(.)(.)(.)\\8", + "aabbccaababcc", + "aabbccaababcc", + 0, + ["aabbccaaba", "a", "a", "b", "b", "c", "c", "a", "a", "b"] ); + +test(); + +function AddRegExpCases( + regexp, str_regexp, pattern, str_pattern, index, matches_array ) { + + // prevent a runtime error + + if ( regexp.exec(pattern) == null || matches_array == null ) { + AddTestCase( + regexp + ".exec(" + str_pattern +")", + matches_array, + regexp.exec(pattern) ); + + return; + } + AddTestCase( + str_regexp + ".exec(" + str_pattern +").length", + matches_array.length, + regexp.exec(pattern).length ); + + AddTestCase( + str_regexp + ".exec(" + str_pattern +").index", + index, + regexp.exec(pattern).index ); + + AddTestCase( + str_regexp + ".exec(" + str_pattern +").input", + pattern, + regexp.exec(pattern).input ); + + AddTestCase( + str_regexp + ".exec(" + str_pattern +").toString()", + matches_array.toString(), + regexp.exec(pattern).toString() ); +/* + var limit = matches_array.length > regexp.exec(pattern).length + ? matches_array.length + : regexp.exec(pattern).length; + + for ( var matches = 0; matches < limit; matches++ ) { + AddTestCase( + str_regexp + ".exec(" + str_pattern +")[" + matches +"]", + matches_array[matches], + regexp.exec(pattern)[matches] ); + } +*/ +} diff --git a/js/src/tests/non262/RegExp/octal-003.js b/js/src/tests/non262/RegExp/octal-003.js new file mode 100644 index 0000000000..58052b2c25 --- /dev/null +++ b/js/src/tests/non262/RegExp/octal-003.js @@ -0,0 +1,86 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + * File Name: RegExp/octal-003.js + * ECMA Section: 15.7.1 + * Description: Based on ECMA 2 Draft 7 February 1999 + * Simple test cases for matching OctalEscapeSequences. + * Author: christine@netscape.com + * Date: 19 February 1999 + * + * Revised: 02 August 2002 + * Author: pschwartau@netscape.com + * + * WHY: the original test expected the regexp /.\011/ + * to match 'a' + String.fromCharCode(0) + '11' + * + * This is incorrect: the string is a 4-character string consisting of + * the characters <'a'>, , <'1'>, <'1'>. By contrast, the \011 in the + * regexp should be parsed as a single token: it is the octal escape sequence + * for the horizontal tab character '\t' === '\u0009' === '\x09' === '\011'. + * + * So the regexp consists of 2 characters: , <'\t'>. + * There is no match between the regexp and the string. + * + * See the testcase non262/RegExp/octal-002.js for an elaboration. + * + */ +var SECTION = "RegExp/octal-003.js"; +var TITLE = "RegExp patterns that contain OctalEscapeSequences"; +var BUGNUMBER="http://scopus/bugsplat/show_bug.cgi?id=346132"; + +printBugNumber(BUGNUMBER); + +AddRegExpCases( /.\011/, "/\\011/", "a" + String.fromCharCode(0) + "11", "a\\011", 0, null ); + +test(); + +function AddRegExpCases( + regexp, str_regexp, pattern, str_pattern, index, matches_array ) { + + // prevent a runtime error + + if ( regexp.exec(pattern) == null || matches_array == null ) { + AddTestCase( + regexp + ".exec(" + str_pattern +")", + matches_array, + regexp.exec(pattern) ); + + return; + } + AddTestCase( + str_regexp + ".exec(" + str_pattern +").length", + matches_array.length, + regexp.exec(pattern).length ); + + AddTestCase( + str_regexp + ".exec(" + str_pattern +").index", + index, + regexp.exec(pattern).index ); + + AddTestCase( + str_regexp + ".exec(" + str_pattern +").input", + escape(pattern), + escape(regexp.exec(pattern).input) ); + + AddTestCase( + str_regexp + ".exec(" + str_pattern +").toString()", + matches_array.toString(), + escape(regexp.exec(pattern).toString()) ); + + var limit = matches_array.length > regexp.exec(pattern).length + ? matches_array.length + : regexp.exec(pattern).length; + + for ( var matches = 0; matches < limit; matches++ ) { + AddTestCase( + str_regexp + ".exec(" + str_pattern +")[" + matches +"]", + matches_array[matches], + escape(regexp.exec(pattern)[matches]) ); + } + +} diff --git a/js/src/tests/non262/RegExp/oom-in-construction.js b/js/src/tests/non262/RegExp/oom-in-construction.js new file mode 100644 index 0000000000..f09cca81b1 --- /dev/null +++ b/js/src/tests/non262/RegExp/oom-in-construction.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty("oomTest")) +var BUGNUMBER = 1471371; +var summary = 'Handle OOM in RegExp'; + +printBugNumber(BUGNUMBER); +printStatus(summary); + +oomTest(function () { + for (var i = 0; i < 10; ++i) { + try { + RegExp("", "gimuyz"); + } catch { } + } +}); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/perlstress-001.js b/js/src/tests/non262/RegExp/perlstress-001.js new file mode 100644 index 0000000000..c073a8f733 --- /dev/null +++ b/js/src/tests/non262/RegExp/perlstress-001.js @@ -0,0 +1,3194 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * + * Date: 2002-07-07 + * SUMMARY: Testing JS RegExp engine against Perl 5 RegExp engine. + * Adjust cnLBOUND, cnUBOUND below to restrict which sections are tested. + * + * This test was created by running various patterns and strings through the + * Perl 5 RegExp engine. We saved the results below to test the JS engine. + * + * NOTE: ECMA/JS and Perl do differ on certain points. We have either commented + * out such sections altogether, or modified them to fit what we expect from JS. + * + * EXAMPLES: + * + * - In JS, regexp captures (/(a) etc./) must hold |undefined| if not used. + * See http://bugzilla.mozilla.org/show_bug.cgi?id=123437. + * By contrast, in Perl, unmatched captures hold the empty string. + * We have modified such sections accordingly. Example: + + pattern = /^([^a-z])|(\^)$/; + string = '.'; + actualmatch = string.match(pattern); + //expectedmatch = Array('.', '.', ''); <<<--- Perl + expectedmatch = Array('.', '.', undefined); <<<--- JS + addThis(); + + + * - In JS, you can't refer to a capture before it's encountered & completed + * + * - Perl supports ] & ^] inside a [], ECMA does not + * + * - ECMA does support (?: (?= and (?! operators, but doesn't support (?< etc. + * + * - ECMA doesn't support (?imsx or (?-imsx + * + * - ECMA doesn't support (?(condition) + * + * - Perl has \Z has end-of-line, ECMA doesn't + * + * - In ECMA, ^ matches only the empty string before the first character + * + * - In ECMA, $ matches only the empty string at end of input (unless multiline) + * + * - ECMA spec says that each atom in a range must be a single character + * + * - ECMA doesn't support \A + * + * - ECMA doesn't have rules for [: + * + */ +//----------------------------------------------------------------------------- +var i = 0; +var BUGNUMBER = 85721; +var summary = 'Testing regular expression edge cases'; +var cnSingleSpace = ' '; +var status = ''; +var statusmessages = new Array(); +var pattern = ''; +var patterns = new Array(); +var string = ''; +var strings = new Array(); +var actualmatch = ''; +var actualmatches = new Array(); +var expectedmatch = ''; +var expectedmatches = new Array(); +var cnLBOUND = 1; +var cnUBOUND = 1000; + + +status = inSection(1); +pattern = /abc/; +string = 'abc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abc'); +addThis(); + +status = inSection(2); +pattern = /abc/; +string = 'xabcy'; +actualmatch = string.match(pattern); +expectedmatch = Array('abc'); +addThis(); + +status = inSection(3); +pattern = /abc/; +string = 'ababc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abc'); +addThis(); + +status = inSection(4); +pattern = /ab*c/; +string = 'abc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abc'); +addThis(); + +status = inSection(5); +pattern = /ab*bc/; +string = 'abc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abc'); +addThis(); + +status = inSection(6); +pattern = /ab*bc/; +string = 'abbc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abbc'); +addThis(); + +status = inSection(7); +pattern = /ab*bc/; +string = 'abbbbc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abbbbc'); +addThis(); + +status = inSection(8); +pattern = /.{1}/; +string = 'abbbbc'; +actualmatch = string.match(pattern); +expectedmatch = Array('a'); +addThis(); + +status = inSection(9); +pattern = /.{3,4}/; +string = 'abbbbc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abbb'); +addThis(); + +status = inSection(10); +pattern = /ab{0,}bc/; +string = 'abbbbc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abbbbc'); +addThis(); + +status = inSection(11); +pattern = /ab+bc/; +string = 'abbc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abbc'); +addThis(); + +status = inSection(12); +pattern = /ab+bc/; +string = 'abbbbc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abbbbc'); +addThis(); + +status = inSection(13); +pattern = /ab{1,}bc/; +string = 'abbbbc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abbbbc'); +addThis(); + +status = inSection(14); +pattern = /ab{1,3}bc/; +string = 'abbbbc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abbbbc'); +addThis(); + +status = inSection(15); +pattern = /ab{3,4}bc/; +string = 'abbbbc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abbbbc'); +addThis(); + +status = inSection(16); +pattern = /ab?bc/; +string = 'abbc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abbc'); +addThis(); + +status = inSection(17); +pattern = /ab?bc/; +string = 'abc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abc'); +addThis(); + +status = inSection(18); +pattern = /ab{0,1}bc/; +string = 'abc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abc'); +addThis(); + +status = inSection(19); +pattern = /ab?c/; +string = 'abc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abc'); +addThis(); + +status = inSection(20); +pattern = /ab{0,1}c/; +string = 'abc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abc'); +addThis(); + +status = inSection(21); +pattern = /^abc$/; +string = 'abc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abc'); +addThis(); + +status = inSection(22); +pattern = /^abc/; +string = 'abcc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abc'); +addThis(); + +status = inSection(23); +pattern = /abc$/; +string = 'aabc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abc'); +addThis(); + +status = inSection(24); +pattern = /^/; +string = 'abc'; +actualmatch = string.match(pattern); +expectedmatch = Array(''); +addThis(); + +status = inSection(25); +pattern = /$/; +string = 'abc'; +actualmatch = string.match(pattern); +expectedmatch = Array(''); +addThis(); + +status = inSection(26); +pattern = /a.c/; +string = 'abc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abc'); +addThis(); + +status = inSection(27); +pattern = /a.c/; +string = 'axc'; +actualmatch = string.match(pattern); +expectedmatch = Array('axc'); +addThis(); + +status = inSection(28); +pattern = /a.*c/; +string = 'axyzc'; +actualmatch = string.match(pattern); +expectedmatch = Array('axyzc'); +addThis(); + +status = inSection(29); +pattern = /a[bc]d/; +string = 'abd'; +actualmatch = string.match(pattern); +expectedmatch = Array('abd'); +addThis(); + +status = inSection(30); +pattern = /a[b-d]e/; +string = 'ace'; +actualmatch = string.match(pattern); +expectedmatch = Array('ace'); +addThis(); + +status = inSection(31); +pattern = /a[b-d]/; +string = 'aac'; +actualmatch = string.match(pattern); +expectedmatch = Array('ac'); +addThis(); + +status = inSection(32); +pattern = /a[-b]/; +string = 'a-'; +actualmatch = string.match(pattern); +expectedmatch = Array('a-'); +addThis(); + +status = inSection(33); +pattern = /a[b-]/; +string = 'a-'; +actualmatch = string.match(pattern); +expectedmatch = Array('a-'); +addThis(); + +status = inSection(34); +pattern = /a]/; +string = 'a]'; +actualmatch = string.match(pattern); +expectedmatch = Array('a]'); +addThis(); + +/* Perl supports ] & ^] inside a [], ECMA does not + pattern = /a[]]b/; + status = inSection(35); + string = 'a]b'; + actualmatch = string.match(pattern); + expectedmatch = Array('a]b'); + addThis(); +*/ + +status = inSection(36); +pattern = /a[^bc]d/; +string = 'aed'; +actualmatch = string.match(pattern); +expectedmatch = Array('aed'); +addThis(); + +status = inSection(37); +pattern = /a[^-b]c/; +string = 'adc'; +actualmatch = string.match(pattern); +expectedmatch = Array('adc'); +addThis(); + +/* Perl supports ] & ^] inside a [], ECMA does not + status = inSection(38); + pattern = /a[^]b]c/; + string = 'adc'; + actualmatch = string.match(pattern); + expectedmatch = Array('adc'); + addThis(); +*/ + +status = inSection(39); +pattern = /\ba\b/; +string = 'a-'; +actualmatch = string.match(pattern); +expectedmatch = Array('a'); +addThis(); + +status = inSection(40); +pattern = /\ba\b/; +string = '-a'; +actualmatch = string.match(pattern); +expectedmatch = Array('a'); +addThis(); + +status = inSection(41); +pattern = /\ba\b/; +string = '-a-'; +actualmatch = string.match(pattern); +expectedmatch = Array('a'); +addThis(); + +status = inSection(42); +pattern = /\By\b/; +string = 'xy'; +actualmatch = string.match(pattern); +expectedmatch = Array('y'); +addThis(); + +status = inSection(43); +pattern = /\by\B/; +string = 'yz'; +actualmatch = string.match(pattern); +expectedmatch = Array('y'); +addThis(); + +status = inSection(44); +pattern = /\By\B/; +string = 'xyz'; +actualmatch = string.match(pattern); +expectedmatch = Array('y'); +addThis(); + +status = inSection(45); +pattern = /\w/; +string = 'a'; +actualmatch = string.match(pattern); +expectedmatch = Array('a'); +addThis(); + +status = inSection(46); +pattern = /\W/; +string = '-'; +actualmatch = string.match(pattern); +expectedmatch = Array('-'); +addThis(); + +status = inSection(47); +pattern = /a\Sb/; +string = 'a-b'; +actualmatch = string.match(pattern); +expectedmatch = Array('a-b'); +addThis(); + +status = inSection(48); +pattern = /\d/; +string = '1'; +actualmatch = string.match(pattern); +expectedmatch = Array('1'); +addThis(); + +status = inSection(49); +pattern = /\D/; +string = '-'; +actualmatch = string.match(pattern); +expectedmatch = Array('-'); +addThis(); + +status = inSection(50); +pattern = /[\w]/; +string = 'a'; +actualmatch = string.match(pattern); +expectedmatch = Array('a'); +addThis(); + +status = inSection(51); +pattern = /[\W]/; +string = '-'; +actualmatch = string.match(pattern); +expectedmatch = Array('-'); +addThis(); + +status = inSection(52); +pattern = /a[\S]b/; +string = 'a-b'; +actualmatch = string.match(pattern); +expectedmatch = Array('a-b'); +addThis(); + +status = inSection(53); +pattern = /[\d]/; +string = '1'; +actualmatch = string.match(pattern); +expectedmatch = Array('1'); +addThis(); + +status = inSection(54); +pattern = /[\D]/; +string = '-'; +actualmatch = string.match(pattern); +expectedmatch = Array('-'); +addThis(); + +status = inSection(55); +pattern = /ab|cd/; +string = 'abc'; +actualmatch = string.match(pattern); +expectedmatch = Array('ab'); +addThis(); + +status = inSection(56); +pattern = /ab|cd/; +string = 'abcd'; +actualmatch = string.match(pattern); +expectedmatch = Array('ab'); +addThis(); + +status = inSection(57); +pattern = /()ef/; +string = 'def'; +actualmatch = string.match(pattern); +expectedmatch = Array('ef', ''); +addThis(); + +status = inSection(58); +pattern = /a\(b/; +string = 'a(b'; +actualmatch = string.match(pattern); +expectedmatch = Array('a(b'); +addThis(); + +status = inSection(59); +pattern = /a\(*b/; +string = 'ab'; +actualmatch = string.match(pattern); +expectedmatch = Array('ab'); +addThis(); + +status = inSection(60); +pattern = /a\(*b/; +string = 'a((b'; +actualmatch = string.match(pattern); +expectedmatch = Array('a((b'); +addThis(); + +status = inSection(61); +pattern = /a\\b/; +string = 'a\\b'; +actualmatch = string.match(pattern); +expectedmatch = Array('a\\b'); +addThis(); + +status = inSection(62); +pattern = /((a))/; +string = 'abc'; +actualmatch = string.match(pattern); +expectedmatch = Array('a', 'a', 'a'); +addThis(); + +status = inSection(63); +pattern = /(a)b(c)/; +string = 'abc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abc', 'a', 'c'); +addThis(); + +status = inSection(64); +pattern = /a+b+c/; +string = 'aabbabc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abc'); +addThis(); + +status = inSection(65); +pattern = /a{1,}b{1,}c/; +string = 'aabbabc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abc'); +addThis(); + +status = inSection(66); +pattern = /a.+?c/; +string = 'abcabc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abc'); +addThis(); + +status = inSection(67); +pattern = /(a+|b)*/; +string = 'ab'; +actualmatch = string.match(pattern); +expectedmatch = Array('ab', 'b'); +addThis(); + +status = inSection(68); +pattern = /(a+|b){0,}/; +string = 'ab'; +actualmatch = string.match(pattern); +expectedmatch = Array('ab', 'b'); +addThis(); + +status = inSection(69); +pattern = /(a+|b)+/; +string = 'ab'; +actualmatch = string.match(pattern); +expectedmatch = Array('ab', 'b'); +addThis(); + +status = inSection(70); +pattern = /(a+|b){1,}/; +string = 'ab'; +actualmatch = string.match(pattern); +expectedmatch = Array('ab', 'b'); +addThis(); + +status = inSection(71); +pattern = /(a+|b)?/; +string = 'ab'; +actualmatch = string.match(pattern); +expectedmatch = Array('a', 'a'); +addThis(); + +status = inSection(72); +pattern = /(a+|b){0,1}/; +string = 'ab'; +actualmatch = string.match(pattern); +expectedmatch = Array('a', 'a'); +addThis(); + +status = inSection(73); +pattern = /[^ab]*/; +string = 'cde'; +actualmatch = string.match(pattern); +expectedmatch = Array('cde'); +addThis(); + +status = inSection(74); +pattern = /([abc])*d/; +string = 'abbbcd'; +actualmatch = string.match(pattern); +expectedmatch = Array('abbbcd', 'c'); +addThis(); + +status = inSection(75); +pattern = /([abc])*bcd/; +string = 'abcd'; +actualmatch = string.match(pattern); +expectedmatch = Array('abcd', 'a'); +addThis(); + +status = inSection(76); +pattern = /a|b|c|d|e/; +string = 'e'; +actualmatch = string.match(pattern); +expectedmatch = Array('e'); +addThis(); + +status = inSection(77); +pattern = /(a|b|c|d|e)f/; +string = 'ef'; +actualmatch = string.match(pattern); +expectedmatch = Array('ef', 'e'); +addThis(); + +status = inSection(78); +pattern = /abcd*efg/; +string = 'abcdefg'; +actualmatch = string.match(pattern); +expectedmatch = Array('abcdefg'); +addThis(); + +status = inSection(79); +pattern = /ab*/; +string = 'xabyabbbz'; +actualmatch = string.match(pattern); +expectedmatch = Array('ab'); +addThis(); + +status = inSection(80); +pattern = /ab*/; +string = 'xayabbbz'; +actualmatch = string.match(pattern); +expectedmatch = Array('a'); +addThis(); + +status = inSection(81); +pattern = /(ab|cd)e/; +string = 'abcde'; +actualmatch = string.match(pattern); +expectedmatch = Array('cde', 'cd'); +addThis(); + +status = inSection(82); +pattern = /[abhgefdc]ij/; +string = 'hij'; +actualmatch = string.match(pattern); +expectedmatch = Array('hij'); +addThis(); + +status = inSection(83); +pattern = /(abc|)ef/; +string = 'abcdef'; +actualmatch = string.match(pattern); +expectedmatch = Array('ef', ''); +addThis(); + +status = inSection(84); +pattern = /(a|b)c*d/; +string = 'abcd'; +actualmatch = string.match(pattern); +expectedmatch = Array('bcd', 'b'); +addThis(); + +status = inSection(85); +pattern = /(ab|ab*)bc/; +string = 'abc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abc', 'a'); +addThis(); + +status = inSection(86); +pattern = /a([bc]*)c*/; +string = 'abc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abc', 'bc'); +addThis(); + +status = inSection(87); +pattern = /a([bc]*)(c*d)/; +string = 'abcd'; +actualmatch = string.match(pattern); +expectedmatch = Array('abcd', 'bc', 'd'); +addThis(); + +status = inSection(88); +pattern = /a([bc]+)(c*d)/; +string = 'abcd'; +actualmatch = string.match(pattern); +expectedmatch = Array('abcd', 'bc', 'd'); +addThis(); + +status = inSection(89); +pattern = /a([bc]*)(c+d)/; +string = 'abcd'; +actualmatch = string.match(pattern); +expectedmatch = Array('abcd', 'b', 'cd'); +addThis(); + +status = inSection(90); +pattern = /a[bcd]*dcdcde/; +string = 'adcdcde'; +actualmatch = string.match(pattern); +expectedmatch = Array('adcdcde'); +addThis(); + +status = inSection(91); +pattern = /(ab|a)b*c/; +string = 'abc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abc', 'ab'); +addThis(); + +status = inSection(92); +pattern = /((a)(b)c)(d)/; +string = 'abcd'; +actualmatch = string.match(pattern); +expectedmatch = Array('abcd', 'abc', 'a', 'b', 'd'); +addThis(); + +status = inSection(93); +pattern = /[a-zA-Z_][a-zA-Z0-9_]*/; +string = 'alpha'; +actualmatch = string.match(pattern); +expectedmatch = Array('alpha'); +addThis(); + +status = inSection(94); +pattern = /^a(bc+|b[eh])g|.h$/; +string = 'abh'; +actualmatch = string.match(pattern); +expectedmatch = Array('bh', undefined); +addThis(); + +status = inSection(95); +pattern = /(bc+d$|ef*g.|h?i(j|k))/; +string = 'effgz'; +actualmatch = string.match(pattern); +expectedmatch = Array('effgz', 'effgz', undefined); +addThis(); + +status = inSection(96); +pattern = /(bc+d$|ef*g.|h?i(j|k))/; +string = 'ij'; +actualmatch = string.match(pattern); +expectedmatch = Array('ij', 'ij', 'j'); +addThis(); + +status = inSection(97); +pattern = /(bc+d$|ef*g.|h?i(j|k))/; +string = 'reffgz'; +actualmatch = string.match(pattern); +expectedmatch = Array('effgz', 'effgz', undefined); +addThis(); + +status = inSection(98); +pattern = /((((((((((a))))))))))/; +string = 'a'; +actualmatch = string.match(pattern); +expectedmatch = Array('a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'); +addThis(); + +status = inSection(99); +pattern = /((((((((((a))))))))))\10/; +string = 'aa'; +actualmatch = string.match(pattern); +expectedmatch = Array('aa', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'); +addThis(); + +status = inSection(100); +pattern = /((((((((((a))))))))))/; +string = 'a!'; +actualmatch = string.match(pattern); +expectedmatch = Array('a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'); +addThis(); + +status = inSection(101); +pattern = /(((((((((a)))))))))/; +string = 'a'; +actualmatch = string.match(pattern); +expectedmatch = Array('a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'); +addThis(); + +status = inSection(102); +pattern = /(.*)c(.*)/; +string = 'abcde'; +actualmatch = string.match(pattern); +expectedmatch = Array('abcde', 'ab', 'de'); +addThis(); + +status = inSection(103); +pattern = /abcd/; +string = 'abcd'; +actualmatch = string.match(pattern); +expectedmatch = Array('abcd'); +addThis(); + +status = inSection(104); +pattern = /a(bc)d/; +string = 'abcd'; +actualmatch = string.match(pattern); +expectedmatch = Array('abcd', 'bc'); +addThis(); + +status = inSection(105); +pattern = /a[-]?c/; +string = 'ac'; +actualmatch = string.match(pattern); +expectedmatch = Array('ac'); +addThis(); + +status = inSection(106); +pattern = /(abc)\1/; +string = 'abcabc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abcabc', 'abc'); +addThis(); + +status = inSection(107); +pattern = /([a-c]*)\1/; +string = 'abcabc'; +actualmatch = string.match(pattern); +expectedmatch = Array('abcabc', 'abc'); +addThis(); + +status = inSection(108); +pattern = /(a)|\1/; +string = 'a'; +actualmatch = string.match(pattern); +expectedmatch = Array('a', 'a'); +addThis(); + +status = inSection(109); +pattern = /(([a-c])b*?\2)*/; +string = 'ababbbcbc'; +actualmatch = string.match(pattern); +expectedmatch = Array('ababb', 'bb', 'b'); +addThis(); + +status = inSection(110); +pattern = /(([a-c])b*?\2){3}/; +string = 'ababbbcbc'; +actualmatch = string.match(pattern); +expectedmatch = Array('ababbbcbc', 'cbc', 'c'); +addThis(); + +/* Can't refer to a capture before it's encountered & completed + status = inSection(111); + pattern = /((\3|b)\2(a)x)+/; + string = 'aaaxabaxbaaxbbax'; + actualmatch = string.match(pattern); + expectedmatch = Array('bbax', 'bbax', 'b', 'a'); + addThis(); + + status = inSection(112); + pattern = /((\3|b)\2(a)){2,}/; + string = 'bbaababbabaaaaabbaaaabba'; + actualmatch = string.match(pattern); + expectedmatch = Array('bbaaaabba', 'bba', 'b', 'a'); + addThis(); +*/ + +status = inSection(113); +pattern = /abc/i; +string = 'ABC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABC'); +addThis(); + +status = inSection(114); +pattern = /abc/i; +string = 'XABCY'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABC'); +addThis(); + +status = inSection(115); +pattern = /abc/i; +string = 'ABABC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABC'); +addThis(); + +status = inSection(116); +pattern = /ab*c/i; +string = 'ABC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABC'); +addThis(); + +status = inSection(117); +pattern = /ab*bc/i; +string = 'ABC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABC'); +addThis(); + +status = inSection(118); +pattern = /ab*bc/i; +string = 'ABBC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABBC'); +addThis(); + +status = inSection(119); +pattern = /ab*?bc/i; +string = 'ABBBBC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABBBBC'); +addThis(); + +status = inSection(120); +pattern = /ab{0,}?bc/i; +string = 'ABBBBC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABBBBC'); +addThis(); + +status = inSection(121); +pattern = /ab+?bc/i; +string = 'ABBC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABBC'); +addThis(); + +status = inSection(122); +pattern = /ab+bc/i; +string = 'ABBBBC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABBBBC'); +addThis(); + +status = inSection(123); +pattern = /ab{1,}?bc/i; +string = 'ABBBBC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABBBBC'); +addThis(); + +status = inSection(124); +pattern = /ab{1,3}?bc/i; +string = 'ABBBBC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABBBBC'); +addThis(); + +status = inSection(125); +pattern = /ab{3,4}?bc/i; +string = 'ABBBBC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABBBBC'); +addThis(); + +status = inSection(126); +pattern = /ab??bc/i; +string = 'ABBC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABBC'); +addThis(); + +status = inSection(127); +pattern = /ab??bc/i; +string = 'ABC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABC'); +addThis(); + +status = inSection(128); +pattern = /ab{0,1}?bc/i; +string = 'ABC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABC'); +addThis(); + +status = inSection(129); +pattern = /ab??c/i; +string = 'ABC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABC'); +addThis(); + +status = inSection(130); +pattern = /ab{0,1}?c/i; +string = 'ABC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABC'); +addThis(); + +status = inSection(131); +pattern = /^abc$/i; +string = 'ABC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABC'); +addThis(); + +status = inSection(132); +pattern = /^abc/i; +string = 'ABCC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABC'); +addThis(); + +status = inSection(133); +pattern = /abc$/i; +string = 'AABC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABC'); +addThis(); + +status = inSection(134); +pattern = /^/i; +string = 'ABC'; +actualmatch = string.match(pattern); +expectedmatch = Array(''); +addThis(); + +status = inSection(135); +pattern = /$/i; +string = 'ABC'; +actualmatch = string.match(pattern); +expectedmatch = Array(''); +addThis(); + +status = inSection(136); +pattern = /a.c/i; +string = 'ABC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABC'); +addThis(); + +status = inSection(137); +pattern = /a.c/i; +string = 'AXC'; +actualmatch = string.match(pattern); +expectedmatch = Array('AXC'); +addThis(); + +status = inSection(138); +pattern = /a.*?c/i; +string = 'AXYZC'; +actualmatch = string.match(pattern); +expectedmatch = Array('AXYZC'); +addThis(); + +status = inSection(139); +pattern = /a[bc]d/i; +string = 'ABD'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABD'); +addThis(); + +status = inSection(140); +pattern = /a[b-d]e/i; +string = 'ACE'; +actualmatch = string.match(pattern); +expectedmatch = Array('ACE'); +addThis(); + +status = inSection(141); +pattern = /a[b-d]/i; +string = 'AAC'; +actualmatch = string.match(pattern); +expectedmatch = Array('AC'); +addThis(); + +status = inSection(142); +pattern = /a[-b]/i; +string = 'A-'; +actualmatch = string.match(pattern); +expectedmatch = Array('A-'); +addThis(); + +status = inSection(143); +pattern = /a[b-]/i; +string = 'A-'; +actualmatch = string.match(pattern); +expectedmatch = Array('A-'); +addThis(); + +status = inSection(144); +pattern = /a]/i; +string = 'A]'; +actualmatch = string.match(pattern); +expectedmatch = Array('A]'); +addThis(); + +/* Perl supports ] & ^] inside a [], ECMA does not + status = inSection(145); + pattern = /a[]]b/i; + string = 'A]B'; + actualmatch = string.match(pattern); + expectedmatch = Array('A]B'); + addThis(); +*/ + +status = inSection(146); +pattern = /a[^bc]d/i; +string = 'AED'; +actualmatch = string.match(pattern); +expectedmatch = Array('AED'); +addThis(); + +status = inSection(147); +pattern = /a[^-b]c/i; +string = 'ADC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ADC'); +addThis(); + +/* Perl supports ] & ^] inside a [], ECMA does not + status = inSection(148); + pattern = /a[^]b]c/i; + string = 'ADC'; + actualmatch = string.match(pattern); + expectedmatch = Array('ADC'); + addThis(); +*/ + +status = inSection(149); +pattern = /ab|cd/i; +string = 'ABC'; +actualmatch = string.match(pattern); +expectedmatch = Array('AB'); +addThis(); + +status = inSection(150); +pattern = /ab|cd/i; +string = 'ABCD'; +actualmatch = string.match(pattern); +expectedmatch = Array('AB'); +addThis(); + +status = inSection(151); +pattern = /()ef/i; +string = 'DEF'; +actualmatch = string.match(pattern); +expectedmatch = Array('EF', ''); +addThis(); + +status = inSection(152); +pattern = /a\(b/i; +string = 'A(B'; +actualmatch = string.match(pattern); +expectedmatch = Array('A(B'); +addThis(); + +status = inSection(153); +pattern = /a\(*b/i; +string = 'AB'; +actualmatch = string.match(pattern); +expectedmatch = Array('AB'); +addThis(); + +status = inSection(154); +pattern = /a\(*b/i; +string = 'A((B'; +actualmatch = string.match(pattern); +expectedmatch = Array('A((B'); +addThis(); + +status = inSection(155); +pattern = /a\\b/i; +string = 'A\\B'; +actualmatch = string.match(pattern); +expectedmatch = Array('A\\B'); +addThis(); + +status = inSection(156); +pattern = /((a))/i; +string = 'ABC'; +actualmatch = string.match(pattern); +expectedmatch = Array('A', 'A', 'A'); +addThis(); + +status = inSection(157); +pattern = /(a)b(c)/i; +string = 'ABC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABC', 'A', 'C'); +addThis(); + +status = inSection(158); +pattern = /a+b+c/i; +string = 'AABBABC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABC'); +addThis(); + +status = inSection(159); +pattern = /a{1,}b{1,}c/i; +string = 'AABBABC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABC'); +addThis(); + +status = inSection(160); +pattern = /a.+?c/i; +string = 'ABCABC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABC'); +addThis(); + +status = inSection(161); +pattern = /a.*?c/i; +string = 'ABCABC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABC'); +addThis(); + +status = inSection(162); +pattern = /a.{0,5}?c/i; +string = 'ABCABC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABC'); +addThis(); + +status = inSection(163); +pattern = /(a+|b)*/i; +string = 'AB'; +actualmatch = string.match(pattern); +expectedmatch = Array('AB', 'B'); +addThis(); + +status = inSection(164); +pattern = /(a+|b){0,}/i; +string = 'AB'; +actualmatch = string.match(pattern); +expectedmatch = Array('AB', 'B'); +addThis(); + +status = inSection(165); +pattern = /(a+|b)+/i; +string = 'AB'; +actualmatch = string.match(pattern); +expectedmatch = Array('AB', 'B'); +addThis(); + +status = inSection(166); +pattern = /(a+|b){1,}/i; +string = 'AB'; +actualmatch = string.match(pattern); +expectedmatch = Array('AB', 'B'); +addThis(); + +status = inSection(167); +pattern = /(a+|b)?/i; +string = 'AB'; +actualmatch = string.match(pattern); +expectedmatch = Array('A', 'A'); +addThis(); + +status = inSection(168); +pattern = /(a+|b){0,1}/i; +string = 'AB'; +actualmatch = string.match(pattern); +expectedmatch = Array('A', 'A'); +addThis(); + +status = inSection(169); +pattern = /(a+|b){0,1}?/i; +string = 'AB'; +actualmatch = string.match(pattern); +expectedmatch = Array('', undefined); +addThis(); + +status = inSection(170); +pattern = /[^ab]*/i; +string = 'CDE'; +actualmatch = string.match(pattern); +expectedmatch = Array('CDE'); +addThis(); + +status = inSection(171); +pattern = /([abc])*d/i; +string = 'ABBBCD'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABBBCD', 'C'); +addThis(); + +status = inSection(172); +pattern = /([abc])*bcd/i; +string = 'ABCD'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABCD', 'A'); +addThis(); + +status = inSection(173); +pattern = /a|b|c|d|e/i; +string = 'E'; +actualmatch = string.match(pattern); +expectedmatch = Array('E'); +addThis(); + +status = inSection(174); +pattern = /(a|b|c|d|e)f/i; +string = 'EF'; +actualmatch = string.match(pattern); +expectedmatch = Array('EF', 'E'); +addThis(); + +status = inSection(175); +pattern = /abcd*efg/i; +string = 'ABCDEFG'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABCDEFG'); +addThis(); + +status = inSection(176); +pattern = /ab*/i; +string = 'XABYABBBZ'; +actualmatch = string.match(pattern); +expectedmatch = Array('AB'); +addThis(); + +status = inSection(177); +pattern = /ab*/i; +string = 'XAYABBBZ'; +actualmatch = string.match(pattern); +expectedmatch = Array('A'); +addThis(); + +status = inSection(178); +pattern = /(ab|cd)e/i; +string = 'ABCDE'; +actualmatch = string.match(pattern); +expectedmatch = Array('CDE', 'CD'); +addThis(); + +status = inSection(179); +pattern = /[abhgefdc]ij/i; +string = 'HIJ'; +actualmatch = string.match(pattern); +expectedmatch = Array('HIJ'); +addThis(); + +status = inSection(180); +pattern = /(abc|)ef/i; +string = 'ABCDEF'; +actualmatch = string.match(pattern); +expectedmatch = Array('EF', ''); +addThis(); + +status = inSection(181); +pattern = /(a|b)c*d/i; +string = 'ABCD'; +actualmatch = string.match(pattern); +expectedmatch = Array('BCD', 'B'); +addThis(); + +status = inSection(182); +pattern = /(ab|ab*)bc/i; +string = 'ABC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABC', 'A'); +addThis(); + +status = inSection(183); +pattern = /a([bc]*)c*/i; +string = 'ABC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABC', 'BC'); +addThis(); + +status = inSection(184); +pattern = /a([bc]*)(c*d)/i; +string = 'ABCD'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABCD', 'BC', 'D'); +addThis(); + +status = inSection(185); +pattern = /a([bc]+)(c*d)/i; +string = 'ABCD'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABCD', 'BC', 'D'); +addThis(); + +status = inSection(186); +pattern = /a([bc]*)(c+d)/i; +string = 'ABCD'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABCD', 'B', 'CD'); +addThis(); + +status = inSection(187); +pattern = /a[bcd]*dcdcde/i; +string = 'ADCDCDE'; +actualmatch = string.match(pattern); +expectedmatch = Array('ADCDCDE'); +addThis(); + +status = inSection(188); +pattern = /(ab|a)b*c/i; +string = 'ABC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABC', 'AB'); +addThis(); + +status = inSection(189); +pattern = /((a)(b)c)(d)/i; +string = 'ABCD'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABCD', 'ABC', 'A', 'B', 'D'); +addThis(); + +status = inSection(190); +pattern = /[a-zA-Z_][a-zA-Z0-9_]*/i; +string = 'ALPHA'; +actualmatch = string.match(pattern); +expectedmatch = Array('ALPHA'); +addThis(); + +status = inSection(191); +pattern = /^a(bc+|b[eh])g|.h$/i; +string = 'ABH'; +actualmatch = string.match(pattern); +expectedmatch = Array('BH', undefined); +addThis(); + +status = inSection(192); +pattern = /(bc+d$|ef*g.|h?i(j|k))/i; +string = 'EFFGZ'; +actualmatch = string.match(pattern); +expectedmatch = Array('EFFGZ', 'EFFGZ', undefined); +addThis(); + +status = inSection(193); +pattern = /(bc+d$|ef*g.|h?i(j|k))/i; +string = 'IJ'; +actualmatch = string.match(pattern); +expectedmatch = Array('IJ', 'IJ', 'J'); +addThis(); + +status = inSection(194); +pattern = /(bc+d$|ef*g.|h?i(j|k))/i; +string = 'REFFGZ'; +actualmatch = string.match(pattern); +expectedmatch = Array('EFFGZ', 'EFFGZ', undefined); +addThis(); + +status = inSection(195); +pattern = /((((((((((a))))))))))/i; +string = 'A'; +actualmatch = string.match(pattern); +expectedmatch = Array('A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'); +addThis(); + +status = inSection(196); +pattern = /((((((((((a))))))))))\10/i; +string = 'AA'; +actualmatch = string.match(pattern); +expectedmatch = Array('AA', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'); +addThis(); + +status = inSection(197); +pattern = /((((((((((a))))))))))/i; +string = 'A!'; +actualmatch = string.match(pattern); +expectedmatch = Array('A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'); +addThis(); + +status = inSection(198); +pattern = /(((((((((a)))))))))/i; +string = 'A'; +actualmatch = string.match(pattern); +expectedmatch = Array('A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'); +addThis(); + +status = inSection(199); +pattern = /(?:(?:(?:(?:(?:(?:(?:(?:(?:(a))))))))))/i; +string = 'A'; +actualmatch = string.match(pattern); +expectedmatch = Array('A', 'A'); +addThis(); + +status = inSection(200); +pattern = /(?:(?:(?:(?:(?:(?:(?:(?:(?:(a|b|c))))))))))/i; +string = 'C'; +actualmatch = string.match(pattern); +expectedmatch = Array('C', 'C'); +addThis(); + +status = inSection(201); +pattern = /(.*)c(.*)/i; +string = 'ABCDE'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABCDE', 'AB', 'DE'); +addThis(); + +status = inSection(202); +pattern = /abcd/i; +string = 'ABCD'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABCD'); +addThis(); + +status = inSection(203); +pattern = /a(bc)d/i; +string = 'ABCD'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABCD', 'BC'); +addThis(); + +status = inSection(204); +pattern = /a[-]?c/i; +string = 'AC'; +actualmatch = string.match(pattern); +expectedmatch = Array('AC'); +addThis(); + +status = inSection(205); +pattern = /(abc)\1/i; +string = 'ABCABC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABCABC', 'ABC'); +addThis(); + +status = inSection(206); +pattern = /([a-c]*)\1/i; +string = 'ABCABC'; +actualmatch = string.match(pattern); +expectedmatch = Array('ABCABC', 'ABC'); +addThis(); + +status = inSection(207); +pattern = /a(?!b)./; +string = 'abad'; +actualmatch = string.match(pattern); +expectedmatch = Array('ad'); +addThis(); + +status = inSection(208); +pattern = /a(?=d)./; +string = 'abad'; +actualmatch = string.match(pattern); +expectedmatch = Array('ad'); +addThis(); + +status = inSection(209); +pattern = /a(?=c|d)./; +string = 'abad'; +actualmatch = string.match(pattern); +expectedmatch = Array('ad'); +addThis(); + +status = inSection(210); +pattern = /a(?:b|c|d)(.)/; +string = 'ace'; +actualmatch = string.match(pattern); +expectedmatch = Array('ace', 'e'); +addThis(); + +status = inSection(211); +pattern = /a(?:b|c|d)*(.)/; +string = 'ace'; +actualmatch = string.match(pattern); +expectedmatch = Array('ace', 'e'); +addThis(); + +status = inSection(212); +pattern = /a(?:b|c|d)+?(.)/; +string = 'ace'; +actualmatch = string.match(pattern); +expectedmatch = Array('ace', 'e'); +addThis(); + +status = inSection(213); +pattern = /a(?:b|c|d)+?(.)/; +string = 'acdbcdbe'; +actualmatch = string.match(pattern); +expectedmatch = Array('acd', 'd'); +addThis(); + +status = inSection(214); +pattern = /a(?:b|c|d)+(.)/; +string = 'acdbcdbe'; +actualmatch = string.match(pattern); +expectedmatch = Array('acdbcdbe', 'e'); +addThis(); + +status = inSection(215); +pattern = /a(?:b|c|d){2}(.)/; +string = 'acdbcdbe'; +actualmatch = string.match(pattern); +expectedmatch = Array('acdb', 'b'); +addThis(); + +status = inSection(216); +pattern = /a(?:b|c|d){4,5}(.)/; +string = 'acdbcdbe'; +actualmatch = string.match(pattern); +expectedmatch = Array('acdbcdb', 'b'); +addThis(); + +status = inSection(217); +pattern = /a(?:b|c|d){4,5}?(.)/; +string = 'acdbcdbe'; +actualmatch = string.match(pattern); +expectedmatch = Array('acdbcd', 'd'); +addThis(); + +// MODIFIED - ECMA has different rules for paren contents +status = inSection(218); +pattern = /((foo)|(bar))*/; +string = 'foobar'; +actualmatch = string.match(pattern); +//expectedmatch = Array('foobar', 'bar', 'foo', 'bar'); +expectedmatch = Array('foobar', 'bar', undefined, 'bar'); +addThis(); + +status = inSection(219); +pattern = /a(?:b|c|d){6,7}(.)/; +string = 'acdbcdbe'; +actualmatch = string.match(pattern); +expectedmatch = Array('acdbcdbe', 'e'); +addThis(); + +status = inSection(220); +pattern = /a(?:b|c|d){6,7}?(.)/; +string = 'acdbcdbe'; +actualmatch = string.match(pattern); +expectedmatch = Array('acdbcdbe', 'e'); +addThis(); + +status = inSection(221); +pattern = /a(?:b|c|d){5,6}(.)/; +string = 'acdbcdbe'; +actualmatch = string.match(pattern); +expectedmatch = Array('acdbcdbe', 'e'); +addThis(); + +status = inSection(222); +pattern = /a(?:b|c|d){5,6}?(.)/; +string = 'acdbcdbe'; +actualmatch = string.match(pattern); +expectedmatch = Array('acdbcdb', 'b'); +addThis(); + +status = inSection(223); +pattern = /a(?:b|c|d){5,7}(.)/; +string = 'acdbcdbe'; +actualmatch = string.match(pattern); +expectedmatch = Array('acdbcdbe', 'e'); +addThis(); + +status = inSection(224); +pattern = /a(?:b|c|d){5,7}?(.)/; +string = 'acdbcdbe'; +actualmatch = string.match(pattern); +expectedmatch = Array('acdbcdb', 'b'); +addThis(); + +status = inSection(225); +pattern = /a(?:b|(c|e){1,2}?|d)+?(.)/; +string = 'ace'; +actualmatch = string.match(pattern); +expectedmatch = Array('ace', 'c', 'e'); +addThis(); + +status = inSection(226); +pattern = /^(.+)?B/; +string = 'AB'; +actualmatch = string.match(pattern); +expectedmatch = Array('AB', 'A'); +addThis(); + +/* MODIFIED - ECMA has different rules for paren contents */ +status = inSection(227); +pattern = /^([^a-z])|(\^)$/; +string = '.'; +actualmatch = string.match(pattern); +//expectedmatch = Array('.', '.', ''); +expectedmatch = Array('.', '.', undefined); +addThis(); + +status = inSection(228); +pattern = /^[<>]&/; +string = '<&OUT'; +actualmatch = string.match(pattern); +expectedmatch = Array('<&'); +addThis(); + +/* Can't refer to a capture before it's encountered & completed + status = inSection(229); + pattern = /^(a\1?){4}$/; + string = 'aaaaaaaaaa'; + actualmatch = string.match(pattern); + expectedmatch = Array('aaaaaaaaaa', 'aaaa'); + addThis(); + + status = inSection(230); + pattern = /^(a(?(1)\1)){4}$/; + string = 'aaaaaaaaaa'; + actualmatch = string.match(pattern); + expectedmatch = Array('aaaaaaaaaa', 'aaaa'); + addThis(); +*/ + +status = inSection(231); +pattern = /((a{4})+)/; +string = 'aaaaaaaaa'; +actualmatch = string.match(pattern); +expectedmatch = Array('aaaaaaaa', 'aaaaaaaa', 'aaaa'); +addThis(); + +status = inSection(232); +pattern = /(((aa){2})+)/; +string = 'aaaaaaaaaa'; +actualmatch = string.match(pattern); +expectedmatch = Array('aaaaaaaa', 'aaaaaaaa', 'aaaa', 'aa'); +addThis(); + +status = inSection(233); +pattern = /(((a{2}){2})+)/; +string = 'aaaaaaaaaa'; +actualmatch = string.match(pattern); +expectedmatch = Array('aaaaaaaa', 'aaaaaaaa', 'aaaa', 'aa'); +addThis(); + +status = inSection(234); +pattern = /(?:(f)(o)(o)|(b)(a)(r))*/; +string = 'foobar'; +actualmatch = string.match(pattern); +//expectedmatch = Array('foobar', 'f', 'o', 'o', 'b', 'a', 'r'); +expectedmatch = Array('foobar', undefined, undefined, undefined, 'b', 'a', 'r'); +addThis(); + +/* ECMA supports (?: (?= and (?! but doesn't support (?< etc. + status = inSection(235); + pattern = /(?<=a)b/; + string = 'ab'; + actualmatch = string.match(pattern); + expectedmatch = Array('b'); + addThis(); + + status = inSection(236); + pattern = /(? + status = inSection(311); + pattern = /(?>a+)b/; + string = 'aaab'; + actualmatch = string.match(pattern); + expectedmatch = Array('aaab'); + addThis(); +*/ + +status = inSection(312); +pattern = /([[:]+)/; + string = 'a:[b]:'; + actualmatch = string.match(pattern); + expectedmatch = Array(':[', ':['); + addThis(); + + status = inSection(313); + pattern = /([[=]+)/; + string = 'a=[b]='; + actualmatch = string.match(pattern); + expectedmatch = Array('=[', '=['); + addThis(); + + status = inSection(314); + pattern = /([[.]+)/; + string = 'a.[b].'; + actualmatch = string.match(pattern); + expectedmatch = Array('.[', '.['); + addThis(); + +/* ECMA doesn't have rules for [: + status = inSection(315); + pattern = /[a[:]b[:c]/; + string = 'abc'; + actualmatch = string.match(pattern); + expectedmatch = Array('abc'); + addThis(); +*/ + +/* ECMA doesn't support (?> + status = inSection(316); + pattern = /((?>a+)b)/; + string = 'aaab'; + actualmatch = string.match(pattern); + expectedmatch = Array('aaab', 'aaab'); + addThis(); + + status = inSection(317); + pattern = /(?>(a+))b/; + string = 'aaab'; + actualmatch = string.match(pattern); + expectedmatch = Array('aaab', 'aaa'); + addThis(); + + status = inSection(318); + pattern = /((?>[^()]+)|\([^()]*\))+/; + string = '((abc(ade)ufh()()x'; + actualmatch = string.match(pattern); + expectedmatch = Array('abc(ade)ufh()()x', 'x'); + addThis(); +*/ + +/* Perl has \Z has end-of-line, ECMA doesn't + status = inSection(319); + pattern = /\Z/; + string = 'a\nb\n'; + actualmatch = string.match(pattern); + expectedmatch = Array(''); + addThis(); + + status = inSection(320); + pattern = /\z/; + string = 'a\nb\n'; + actualmatch = string.match(pattern); + expectedmatch = Array(''); + addThis(); +*/ + + status = inSection(321); + pattern = /$/; + string = 'a\nb\n'; + actualmatch = string.match(pattern); + expectedmatch = Array(''); + addThis(); + +/* Perl has \Z has end-of-line, ECMA doesn't + status = inSection(322); + pattern = /\Z/; + string = 'b\na\n'; + actualmatch = string.match(pattern); + expectedmatch = Array(''); + addThis(); + + status = inSection(323); + pattern = /\z/; + string = 'b\na\n'; + actualmatch = string.match(pattern); + expectedmatch = Array(''); + addThis(); +*/ + + status = inSection(324); + pattern = /$/; + string = 'b\na\n'; + actualmatch = string.match(pattern); + expectedmatch = Array(''); + addThis(); + +/* Perl has \Z has end-of-line, ECMA doesn't + status = inSection(325); + pattern = /\Z/; + string = 'b\na'; + actualmatch = string.match(pattern); + expectedmatch = Array(''); + addThis(); + + status = inSection(326); + pattern = /\z/; + string = 'b\na'; + actualmatch = string.match(pattern); + expectedmatch = Array(''); + addThis(); +*/ + + status = inSection(327); + pattern = /$/; + string = 'b\na'; + actualmatch = string.match(pattern); + expectedmatch = Array(''); + addThis(); + +/* Perl has \Z has end-of-line, ECMA doesn't + status = inSection(328); + pattern = /\Z/m; + string = 'a\nb\n'; + actualmatch = string.match(pattern); + expectedmatch = Array(''); + addThis(); + + status = inSection(329); + pattern = /\z/m; + string = 'a\nb\n'; + actualmatch = string.match(pattern); + expectedmatch = Array(''); + addThis(); +*/ + + status = inSection(330); + pattern = /$/m; + string = 'a\nb\n'; + actualmatch = string.match(pattern); + expectedmatch = Array(''); + addThis(); + +/* Perl has \Z has end-of-line, ECMA doesn't + status = inSection(331); + pattern = /\Z/m; + string = 'b\na\n'; + actualmatch = string.match(pattern); + expectedmatch = Array(''); + addThis(); + + status = inSection(332); + pattern = /\z/m; + string = 'b\na\n'; + actualmatch = string.match(pattern); + expectedmatch = Array(''); + addThis(); +*/ + + status = inSection(333); + pattern = /$/m; + string = 'b\na\n'; + actualmatch = string.match(pattern); + expectedmatch = Array(''); + addThis(); + +/* Perl has \Z has end-of-line, ECMA doesn't + status = inSection(334); + pattern = /\Z/m; + string = 'b\na'; + actualmatch = string.match(pattern); + expectedmatch = Array(''); + addThis(); + + status = inSection(335); + pattern = /\z/m; + string = 'b\na'; + actualmatch = string.match(pattern); + expectedmatch = Array(''); + addThis(); +*/ + + status = inSection(336); + pattern = /$/m; + string = 'b\na'; + actualmatch = string.match(pattern); + expectedmatch = Array(''); + addThis(); + +/* Perl has \Z has end-of-line, ECMA doesn't + status = inSection(337); + pattern = /a\Z/; + string = 'b\na\n'; + actualmatch = string.match(pattern); + expectedmatch = Array('a'); + addThis(); +*/ + +/* $ only matches end of input unless multiline + status = inSection(338); + pattern = /a$/; + string = 'b\na\n'; + actualmatch = string.match(pattern); + expectedmatch = Array('a'); + addThis(); +*/ + +/* Perl has \Z has end-of-line, ECMA doesn't + status = inSection(339); + pattern = /a\Z/; + string = 'b\na'; + actualmatch = string.match(pattern); + expectedmatch = Array('a'); + addThis(); + + status = inSection(340); + pattern = /a\z/; + string = 'b\na'; + actualmatch = string.match(pattern); + expectedmatch = Array('a'); + addThis(); +*/ + + status = inSection(341); + pattern = /a$/; + string = 'b\na'; + actualmatch = string.match(pattern); + expectedmatch = Array('a'); + addThis(); + + status = inSection(342); + pattern = /a$/m; + string = 'a\nb\n'; + actualmatch = string.match(pattern); + expectedmatch = Array('a'); + addThis(); + +/* Perl has \Z has end-of-line, ECMA doesn't + status = inSection(343); + pattern = /a\Z/m; + string = 'b\na\n'; + actualmatch = string.match(pattern); + expectedmatch = Array('a'); + addThis(); +*/ + + status = inSection(344); + pattern = /a$/m; + string = 'b\na\n'; + actualmatch = string.match(pattern); + expectedmatch = Array('a'); + addThis(); + +/* Perl has \Z has end-of-line, ECMA doesn't + status = inSection(345); + pattern = /a\Z/m; + string = 'b\na'; + actualmatch = string.match(pattern); + expectedmatch = Array('a'); + addThis(); + + status = inSection(346); + pattern = /a\z/m; + string = 'b\na'; + actualmatch = string.match(pattern); + expectedmatch = Array('a'); + addThis(); +*/ + + status = inSection(347); + pattern = /a$/m; + string = 'b\na'; + actualmatch = string.match(pattern); + expectedmatch = Array('a'); + addThis(); + +/* Perl has \Z has end-of-line, ECMA doesn't + status = inSection(348); + pattern = /aa\Z/; + string = 'b\naa\n'; + actualmatch = string.match(pattern); + expectedmatch = Array('aa'); + addThis(); +*/ + +/* $ only matches end of input unless multiline + status = inSection(349); + pattern = /aa$/; + string = 'b\naa\n'; + actualmatch = string.match(pattern); + expectedmatch = Array('aa'); + addThis(); +*/ + +/* Perl has \Z has end-of-line, ECMA doesn't + status = inSection(350); + pattern = /aa\Z/; + string = 'b\naa'; + actualmatch = string.match(pattern); + expectedmatch = Array('aa'); + addThis(); + + status = inSection(351); + pattern = /aa\z/; + string = 'b\naa'; + actualmatch = string.match(pattern); + expectedmatch = Array('aa'); + addThis(); +*/ + + status = inSection(352); + pattern = /aa$/; + string = 'b\naa'; + actualmatch = string.match(pattern); + expectedmatch = Array('aa'); + addThis(); + + status = inSection(353); + pattern = /aa$/m; + string = 'aa\nb\n'; + actualmatch = string.match(pattern); + expectedmatch = Array('aa'); + addThis(); + +/* Perl has \Z has end-of-line, ECMA doesn't + status = inSection(354); + pattern = /aa\Z/m; + string = 'b\naa\n'; + actualmatch = string.match(pattern); + expectedmatch = Array('aa'); + addThis(); +*/ + + status = inSection(355); + pattern = /aa$/m; + string = 'b\naa\n'; + actualmatch = string.match(pattern); + expectedmatch = Array('aa'); + addThis(); + +/* Perl has \Z has end-of-line, ECMA doesn't + status = inSection(356); + pattern = /aa\Z/m; + string = 'b\naa'; + actualmatch = string.match(pattern); + expectedmatch = Array('aa'); + addThis(); + + status = inSection(357); + pattern = /aa\z/m; + string = 'b\naa'; + actualmatch = string.match(pattern); + expectedmatch = Array('aa'); + addThis(); +*/ + + status = inSection(358); + pattern = /aa$/m; + string = 'b\naa'; + actualmatch = string.match(pattern); + expectedmatch = Array('aa'); + addThis(); + +/* Perl has \Z has end-of-line, ECMA doesn't + status = inSection(359); + pattern = /ab\Z/; + string = 'b\nab\n'; + actualmatch = string.match(pattern); + expectedmatch = Array('ab'); + addThis(); +*/ + +/* $ only matches end of input unless multiline + status = inSection(360); + pattern = /ab$/; + string = 'b\nab\n'; + actualmatch = string.match(pattern); + expectedmatch = Array('ab'); + addThis(); +*/ + +/* Perl has \Z has end-of-line, ECMA doesn't + status = inSection(361); + pattern = /ab\Z/; + string = 'b\nab'; + actualmatch = string.match(pattern); + expectedmatch = Array('ab'); + addThis(); + + status = inSection(362); + pattern = /ab\z/; + string = 'b\nab'; + actualmatch = string.match(pattern); + expectedmatch = Array('ab'); + addThis(); +*/ + + status = inSection(363); + pattern = /ab$/; + string = 'b\nab'; + actualmatch = string.match(pattern); + expectedmatch = Array('ab'); + addThis(); + + status = inSection(364); + pattern = /ab$/m; + string = 'ab\nb\n'; + actualmatch = string.match(pattern); + expectedmatch = Array('ab'); + addThis(); + +/* Perl has \Z has end-of-line, ECMA doesn't + status = inSection(365); + pattern = /ab\Z/m; + string = 'b\nab\n'; + actualmatch = string.match(pattern); + expectedmatch = Array('ab'); + addThis(); +*/ + + status = inSection(366); + pattern = /ab$/m; + string = 'b\nab\n'; + actualmatch = string.match(pattern); + expectedmatch = Array('ab'); + addThis(); + +/* Perl has \Z has end-of-line, ECMA doesn't + status = inSection(367); + pattern = /ab\Z/m; + string = 'b\nab'; + actualmatch = string.match(pattern); + expectedmatch = Array('ab'); + addThis(); + + status = inSection(368); + pattern = /ab\z/m; + string = 'b\nab'; + actualmatch = string.match(pattern); + expectedmatch = Array('ab'); + addThis(); +*/ + + status = inSection(369); + pattern = /ab$/m; + string = 'b\nab'; + actualmatch = string.match(pattern); + expectedmatch = Array('ab'); + addThis(); + +/* Perl has \Z has end-of-line, ECMA doesn't + status = inSection(370); + pattern = /abb\Z/; + string = 'b\nabb\n'; + actualmatch = string.match(pattern); + expectedmatch = Array('abb'); + addThis(); +*/ + +/* $ only matches end of input unless multiline + status = inSection(371); + pattern = /abb$/; + string = 'b\nabb\n'; + actualmatch = string.match(pattern); + expectedmatch = Array('abb'); + addThis(); +*/ + +/* Perl has \Z has end-of-line, ECMA doesn't + status = inSection(372); + pattern = /abb\Z/; + string = 'b\nabb'; + actualmatch = string.match(pattern); + expectedmatch = Array('abb'); + addThis(); + + status = inSection(373); + pattern = /abb\z/; + string = 'b\nabb'; + actualmatch = string.match(pattern); + expectedmatch = Array('abb'); + addThis(); +*/ + + status = inSection(374); + pattern = /abb$/; + string = 'b\nabb'; + actualmatch = string.match(pattern); + expectedmatch = Array('abb'); + addThis(); + + status = inSection(375); + pattern = /abb$/m; + string = 'abb\nb\n'; + actualmatch = string.match(pattern); + expectedmatch = Array('abb'); + addThis(); + +/* Perl has \Z has end-of-line, ECMA doesn't + status = inSection(376); + pattern = /abb\Z/m; + string = 'b\nabb\n'; + actualmatch = string.match(pattern); + expectedmatch = Array('abb'); + addThis(); +*/ + + status = inSection(377); + pattern = /abb$/m; + string = 'b\nabb\n'; + actualmatch = string.match(pattern); + expectedmatch = Array('abb'); + addThis(); + +/* Perl has \Z has end-of-line, ECMA doesn't + status = inSection(378); + pattern = /abb\Z/m; + string = 'b\nabb'; + actualmatch = string.match(pattern); + expectedmatch = Array('abb'); + addThis(); + + status = inSection(379); + pattern = /abb\z/m; + string = 'b\nabb'; + actualmatch = string.match(pattern); + expectedmatch = Array('abb'); + addThis(); +*/ + + status = inSection(380); + pattern = /abb$/m; + string = 'b\nabb'; + actualmatch = string.match(pattern); + expectedmatch = Array('abb'); + addThis(); + + status = inSection(381); + pattern = /(^|x)(c)/; + string = 'ca'; + actualmatch = string.match(pattern); + expectedmatch = Array('c', '', 'c'); + addThis(); + + status = inSection(382); + pattern = /foo.bart/; + string = 'foo.bart'; + actualmatch = string.match(pattern); + expectedmatch = Array('foo.bart'); + addThis(); + + status = inSection(383); + pattern = /^d[x][x][x]/m; + string = 'abcd\ndxxx'; + actualmatch = string.match(pattern); + expectedmatch = Array('dxxx'); + addThis(); + + status = inSection(384); + pattern = /tt+$/; + string = 'xxxtt'; + actualmatch = string.match(pattern); + expectedmatch = Array('tt'); + addThis(); + +/* ECMA spec says that each atom in a range must be a single character + status = inSection(385); + pattern = /([a-\d]+)/; + string = 'za-9z'; + actualmatch = string.match(pattern); + expectedmatch = Array('9', '9'); + addThis(); + + status = inSection(386); + pattern = /([\d-z]+)/; + string = 'a0-za'; + actualmatch = string.match(pattern); + expectedmatch = Array('0-z', '0-z'); + addThis(); +*/ + +/* ECMA doesn't support [: + status = inSection(387); + pattern = /([a-[:digit:]]+)/; + string = 'za-9z'; + actualmatch = string.match(pattern); + expectedmatch = Array('a-9', 'a-9'); + addThis(); + + status = inSection(388); + pattern = /([[:digit:]-z]+)/; + string = '=0-z='; + actualmatch = string.match(pattern); + expectedmatch = Array('0-z', '0-z'); + addThis(); + + status = inSection(389); + pattern = /([[:digit:]-[:alpha:]]+)/; + string = '=0-z='; + actualmatch = string.match(pattern); + expectedmatch = Array('0-z', '0-z'); + addThis(); +*/ + + status = inSection(390); + pattern = /(\d+\.\d+)/; + string = '3.1415926'; + actualmatch = string.match(pattern); + expectedmatch = Array('3.1415926', '3.1415926'); + addThis(); + + status = inSection(391); + pattern = /\.c(pp|xx|c)?$/i; + string = 'IO.c'; + actualmatch = string.match(pattern); + expectedmatch = Array('.c', undefined); + addThis(); + + status = inSection(392); + pattern = /(\.c(pp|xx|c)?$)/i; + string = 'IO.c'; + actualmatch = string.match(pattern); + expectedmatch = Array('.c', '.c', undefined); + addThis(); + + status = inSection(393); + pattern = /(^|a)b/; + string = 'ab'; + actualmatch = string.match(pattern); + expectedmatch = Array('ab', 'a'); + addThis(); + + status = inSection(394); + pattern = /^([ab]*?)(b)?(c)$/; + string = 'abac'; + actualmatch = string.match(pattern); + expectedmatch = Array('abac', 'aba', undefined, 'c'); + addThis(); + + status = inSection(395); + pattern = /^(?:.,){2}c/i; + string = 'a,b,c'; + actualmatch = string.match(pattern); + expectedmatch = Array('a,b,c'); + addThis(); + + status = inSection(396); + pattern = /^(.,){2}c/i; + string = 'a,b,c'; + actualmatch = string.match(pattern); + expectedmatch = Array('a,b,c', 'b,'); + addThis(); + + status = inSection(397); + pattern = /^(?:[^,]*,){2}c/; + string = 'a,b,c'; + actualmatch = string.match(pattern); + expectedmatch = Array('a,b,c'); + addThis(); + + status = inSection(398); + pattern = /^([^,]*,){2}c/; + string = 'a,b,c'; + actualmatch = string.match(pattern); + expectedmatch = Array('a,b,c', 'b,'); + addThis(); + + status = inSection(399); + pattern = /^([^,]*,){3}d/; + string = 'aaa,b,c,d'; + actualmatch = string.match(pattern); + expectedmatch = Array('aaa,b,c,d', 'c,'); + addThis(); + + status = inSection(400); + pattern = /^([^,]*,){3,}d/; + string = 'aaa,b,c,d'; + actualmatch = string.match(pattern); + expectedmatch = Array('aaa,b,c,d', 'c,'); + addThis(); + + status = inSection(401); + pattern = /^([^,]*,){0,3}d/; + string = 'aaa,b,c,d'; + actualmatch = string.match(pattern); + expectedmatch = Array('aaa,b,c,d', 'c,'); + addThis(); + + status = inSection(402); + pattern = /^([^,]{1,3},){3}d/i; + string = 'aaa,b,c,d'; + actualmatch = string.match(pattern); + expectedmatch = Array('aaa,b,c,d', 'c,'); + addThis(); + + status = inSection(403); + pattern = /^([^,]{1,3},){3,}d/; + string = 'aaa,b,c,d'; + actualmatch = string.match(pattern); + expectedmatch = Array('aaa,b,c,d', 'c,'); + addThis(); + + status = inSection(404); + pattern = /^([^,]{1,3},){0,3}d/; + string = 'aaa,b,c,d'; + actualmatch = string.match(pattern); + expectedmatch = Array('aaa,b,c,d', 'c,'); + addThis(); + + status = inSection(405); + pattern = /^([^,]{1,},){3}d/; + string = 'aaa,b,c,d'; + actualmatch = string.match(pattern); + expectedmatch = Array('aaa,b,c,d', 'c,'); + addThis(); + + status = inSection(406); + pattern = /^([^,]{1,},){3,}d/; + string = 'aaa,b,c,d'; + actualmatch = string.match(pattern); + expectedmatch = Array('aaa,b,c,d', 'c,'); + addThis(); + + status = inSection(407); + pattern = /^([^,]{1,},){0,3}d/; + string = 'aaa,b,c,d'; + actualmatch = string.match(pattern); + expectedmatch = Array('aaa,b,c,d', 'c,'); + addThis(); + + status = inSection(408); + pattern = /^([^,]{0,3},){3}d/i; + string = 'aaa,b,c,d'; + actualmatch = string.match(pattern); + expectedmatch = Array('aaa,b,c,d', 'c,'); + addThis(); + + status = inSection(409); + pattern = /^([^,]{0,3},){3,}d/; + string = 'aaa,b,c,d'; + actualmatch = string.match(pattern); + expectedmatch = Array('aaa,b,c,d', 'c,'); + addThis(); + + status = inSection(410); + pattern = /^([^,]{0,3},){0,3}d/; + string = 'aaa,b,c,d'; + actualmatch = string.match(pattern); + expectedmatch = Array('aaa,b,c,d', 'c,'); + addThis(); + +/* ECMA doesn't support \A + status = inSection(411); + pattern = /(?!\A)x/m; + string = 'a\nxb\n'; + actualmatch = string.match(pattern); + expectedmatch = Array('\n'); + addThis(); +*/ + + status = inSection(412); + pattern = /^(a(b)?)+$/; + string = 'aba'; + actualmatch = string.match(pattern); + expectedmatch = Array('aba', 'a', undefined); + addThis(); + + status = inSection(413); + pattern = /^(aa(bb)?)+$/; + string = 'aabbaa'; + actualmatch = string.match(pattern); + expectedmatch = Array('aabbaa', 'aa', undefined); + addThis(); + + status = inSection(414); + pattern = /^.{9}abc.*\n/m; + string = '123\nabcabcabcabc\n'; + actualmatch = string.match(pattern); + expectedmatch = Array('abcabcabcabc\n'); + addThis(); + + status = inSection(415); + pattern = /^(a)?a$/; + string = 'a'; + actualmatch = string.match(pattern); + expectedmatch = Array('a', undefined); + addThis(); + + status = inSection(416); + pattern = /^(a\1?)(a\1?)(a\2?)(a\3?)$/; + string = 'aaaaaa'; + actualmatch = string.match(pattern); + expectedmatch = Array('aaaaaa', 'a', 'aa', 'a', 'aa'); + addThis(); + +/* Can't refer to a capture before it's encountered & completed + status = inSection(417); + pattern = /^(a\1?){4}$/; + string = 'aaaaaa'; + actualmatch = string.match(pattern); + expectedmatch = Array('aaaaaa', 'aaa'); + addThis(); +*/ + + status = inSection(418); + pattern = /^(0+)?(?:x(1))?/; + string = 'x1'; + actualmatch = string.match(pattern); + expectedmatch = Array('x1', undefined, '1'); + addThis(); + + status = inSection(419); + pattern = /^([0-9a-fA-F]+)(?:x([0-9a-fA-F]+)?)(?:x([0-9a-fA-F]+))?/; + string = '012cxx0190'; + actualmatch = string.match(pattern); + expectedmatch = Array('012cxx0190', '012c', undefined, '0190'); + addThis(); + + status = inSection(420); + pattern = /^(b+?|a){1,2}c/; + string = 'bbbac'; + actualmatch = string.match(pattern); + expectedmatch = Array('bbbac', 'a'); + addThis(); + + status = inSection(421); + pattern = /^(b+?|a){1,2}c/; + string = 'bbbbac'; + actualmatch = string.match(pattern); + expectedmatch = Array('bbbbac', 'a'); + addThis(); + + status = inSection(422); + pattern = /((?:aaaa|bbbb)cccc)?/; + string = 'aaaacccc'; + actualmatch = string.match(pattern); + expectedmatch = Array('aaaacccc', 'aaaacccc'); + addThis(); + + status = inSection(423); + pattern = /((?:aaaa|bbbb)cccc)?/; + string = 'bbbbcccc'; + actualmatch = string.match(pattern); + expectedmatch = Array('bbbbcccc', 'bbbbcccc'); + addThis(); + + + + +//----------------------------------------------------------------------------- + test(); +//----------------------------------------------------------------------------- + + + + function addThis() + { + if(omitCurrentSection()) + return; + + statusmessages[i] = status; + patterns[i] = pattern; + strings[i] = string; + actualmatches[i] = actualmatch; + expectedmatches[i] = expectedmatch; + i++; + } + + + function omitCurrentSection() + { + try + { + // current section number is in global status variable + var n = status.match(/(\d+)/)[1]; + return ((n < cnLBOUND) || (n > cnUBOUND)); + } + catch(e) + { + return false; + } + } + + + function test() + { + printBugNumber(BUGNUMBER); + printStatus (summary); + testRegExp(statusmessages, patterns, strings, actualmatches, expectedmatches); + } diff --git a/js/src/tests/non262/RegExp/perlstress-002.js b/js/src/tests/non262/RegExp/perlstress-002.js new file mode 100644 index 0000000000..288cd9ed8b --- /dev/null +++ b/js/src/tests/non262/RegExp/perlstress-002.js @@ -0,0 +1,1806 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * + * Date: 2002-07-07 + * SUMMARY: Testing JS RegExp engine against Perl 5 RegExp engine. + * Adjust cnLBOUND, cnUBOUND below to restrict which sections are tested. + * + * This test was created by running various patterns and strings through the + * Perl 5 RegExp engine. We saved the results below to test the JS engine. + * + * Each of the examples below is a negative test; that is, each produces a + * null match in Perl. Thus we set |expectedmatch| = |null| in each section. + * + * NOTE: ECMA/JS and Perl do differ on certain points. We have either commented + * out such sections altogether, or modified them to fit what we expect from JS. + * + * EXAMPLES: + * + * - ECMA does support (?: (?= and (?! operators, but doesn't support (?< etc. + * + * - ECMA doesn't support (?(condition) + * + */ +//----------------------------------------------------------------------------- +var i = 0; +var BUGNUMBER = 85721; +var summary = 'Testing regular expression edge cases'; +var cnSingleSpace = ' '; +var status = ''; +var statusmessages = new Array(); +var pattern = ''; +var patterns = new Array(); +var string = ''; +var strings = new Array(); +var actualmatch = ''; +var actualmatches = new Array(); +var expectedmatch = ''; +var expectedmatches = new Array(); +var cnLBOUND = 0; +var cnUBOUND = 1000; + + +status = inSection(1); +pattern = /abc/; +string = 'xbc'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(2); +pattern = /abc/; +string = 'axc'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(3); +pattern = /abc/; +string = 'abx'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(4); +pattern = /ab+bc/; +string = 'abc'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(5); +pattern = /ab+bc/; +string = 'abq'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(6); +pattern = /ab{1,}bc/; +string = 'abq'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(7); +pattern = /ab{4,5}bc/; +string = 'abbbbc'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(8); +pattern = /ab?bc/; +string = 'abbbbc'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(9); +pattern = /^abc$/; +string = 'abcc'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(10); +pattern = /^abc$/; +string = 'aabc'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(11); +pattern = /abc$/; +string = 'aabcd'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(12); +pattern = /a.*c/; +string = 'axyzd'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(13); +pattern = /a[bc]d/; +string = 'abc'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(14); +pattern = /a[b-d]e/; +string = 'abd'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(15); +pattern = /a[^bc]d/; +string = 'abd'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(16); +pattern = /a[^-b]c/; +string = 'a-c'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(17); +pattern = /a[^]b]c/; +string = 'a]c'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(18); +pattern = /\by\b/; +string = 'xy'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(19); +pattern = /\by\b/; +string = 'yz'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(20); +pattern = /\by\b/; +string = 'xyz'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(21); +pattern = /\Ba\B/; +string = 'a-'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(22); +pattern = /\Ba\B/; +string = '-a'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(23); +pattern = /\Ba\B/; +string = '-a-'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(24); +pattern = /\w/; +string = '-'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(25); +pattern = /\W/; +string = 'a'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(26); +pattern = /a\sb/; +string = 'a-b'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(27); +pattern = /\d/; +string = '-'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(28); +pattern = /\D/; +string = '1'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(29); +pattern = /[\w]/; +string = '-'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(30); +pattern = /[\W]/; +string = 'a'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(31); +pattern = /a[\s]b/; +string = 'a-b'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(32); +pattern = /[\d]/; +string = '-'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(33); +pattern = /[\D]/; +string = '1'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(34); +pattern = /$b/; +string = 'b'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(35); +pattern = /^(ab|cd)e/; +string = 'abcde'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(36); +pattern = /a[bcd]+dcdcde/; +string = 'adcdcde'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(37); +pattern = /(bc+d$|ef*g.|h?i(j|k))/; +string = 'effg'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(38); +pattern = /(bc+d$|ef*g.|h?i(j|k))/; +string = 'bcdd'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(39); +pattern = /[k]/; +string = 'ab'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +// MODIFIED - ECMA has different rules for paren contents. +status = inSection(40); +pattern = /(a)|\1/; +string = 'x'; +actualmatch = string.match(pattern); +//expectedmatch = null; +expectedmatch = Array("", undefined); +addThis(); + +// MODIFIED - ECMA has different rules for paren contents. +status = inSection(41); +pattern = /((\3|b)\2(a)x)+/; +string = 'aaxabxbaxbbx'; +actualmatch = string.match(pattern); +//expectedmatch = null; +expectedmatch = Array("ax", "ax", "", "a"); +addThis(); + +status = inSection(42); +pattern = /abc/i; +string = 'XBC'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(43); +pattern = /abc/i; +string = 'AXC'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(44); +pattern = /abc/i; +string = 'ABX'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(45); +pattern = /ab+bc/i; +string = 'ABC'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(46); +pattern = /ab+bc/i; +string = 'ABQ'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(47); +pattern = /ab{1,}bc/i; +string = 'ABQ'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(48); +pattern = /ab{4,5}?bc/i; +string = 'ABBBBC'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(49); +pattern = /ab??bc/i; +string = 'ABBBBC'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(50); +pattern = /^abc$/i; +string = 'ABCC'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(51); +pattern = /^abc$/i; +string = 'AABC'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(52); +pattern = /a.*c/i; +string = 'AXYZD'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(53); +pattern = /a[bc]d/i; +string = 'ABC'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(54); +pattern = /a[b-d]e/i; +string = 'ABD'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(55); +pattern = /a[^bc]d/i; +string = 'ABD'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(56); +pattern = /a[^-b]c/i; +string = 'A-C'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(57); +pattern = /a[^]b]c/i; +string = 'A]C'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(58); +pattern = /$b/i; +string = 'B'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(59); +pattern = /^(ab|cd)e/i; +string = 'ABCDE'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(60); +pattern = /a[bcd]+dcdcde/i; +string = 'ADCDCDE'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(61); +pattern = /(bc+d$|ef*g.|h?i(j|k))/i; +string = 'EFFG'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(62); +pattern = /(bc+d$|ef*g.|h?i(j|k))/i; +string = 'BCDD'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(63); +pattern = /[k]/i; +string = 'AB'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(64); +pattern = /^(a\1?){4}$/; +string = 'aaaaaaaaa'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(65); +pattern = /^(a\1?){4}$/; +string = 'aaaaaaaaaaa'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +/* ECMA doesn't support (?( + status = inSection(66); + pattern = /^(a(?(1)\1)){4}$/; + string = 'aaaaaaaaa'; + actualmatch = string.match(pattern); + expectedmatch = null; + addThis(); + + status = inSection(67); + pattern = /^(a(?(1)\1)){4}$/; + string = 'aaaaaaaaaaa'; + actualmatch = string.match(pattern); + expectedmatch = null; + addThis(); +*/ + +/* ECMA doesn't support (?< + status = inSection(68); + pattern = /(?<=a)b/; + string = 'cb'; + actualmatch = string.match(pattern); + expectedmatch = null; + addThis(); + + status = inSection(69); + pattern = /(?<=a)b/; + string = 'b'; + actualmatch = string.match(pattern); + expectedmatch = null; + addThis(); + + status = inSection(70); + pattern = /(?a+)ab/; +string = 'aaab'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(106); +pattern = /a\Z/; +string = 'a\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(107); +pattern = /a\z/; +string = 'a\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(108); +pattern = /a$/; +string = 'a\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(109); +pattern = /a\z/; +string = 'b\na\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(110); +pattern = /a\z/m; +string = 'a\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(111); +pattern = /a\z/m; +string = 'b\na\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(112); +pattern = /aa\Z/; +string = 'aa\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(113); +pattern = /aa\z/; +string = 'aa\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(114); +pattern = /aa$/; +string = 'aa\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(115); +pattern = /aa\z/; +string = 'b\naa\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(116); +pattern = /aa\z/m; +string = 'aa\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(117); +pattern = /aa\z/m; +string = 'b\naa\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(118); +pattern = /aa\Z/; +string = 'ac\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(119); +pattern = /aa\z/; +string = 'ac\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(120); +pattern = /aa$/; +string = 'ac\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(121); +pattern = /aa\Z/; +string = 'b\nac\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(122); +pattern = /aa\z/; +string = 'b\nac\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(123); +pattern = /aa$/; +string = 'b\nac\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(124); +pattern = /aa\Z/; +string = 'b\nac'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(125); +pattern = /aa\z/; +string = 'b\nac'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(126); +pattern = /aa$/; +string = 'b\nac'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(127); +pattern = /aa\Z/m; +string = 'ac\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(128); +pattern = /aa\z/m; +string = 'ac\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(129); +pattern = /aa$/m; +string = 'ac\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(130); +pattern = /aa\Z/m; +string = 'b\nac\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(131); +pattern = /aa\z/m; +string = 'b\nac\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(132); +pattern = /aa$/m; +string = 'b\nac\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(133); +pattern = /aa\Z/m; +string = 'b\nac'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(134); +pattern = /aa\z/m; +string = 'b\nac'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(135); +pattern = /aa$/m; +string = 'b\nac'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(136); +pattern = /aa\Z/; +string = 'ca\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(137); +pattern = /aa\z/; +string = 'ca\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(138); +pattern = /aa$/; +string = 'ca\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(139); +pattern = /aa\Z/; +string = 'b\nca\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(140); +pattern = /aa\z/; +string = 'b\nca\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(141); +pattern = /aa$/; +string = 'b\nca\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(142); +pattern = /aa\Z/; +string = 'b\nca'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(143); +pattern = /aa\z/; +string = 'b\nca'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(144); +pattern = /aa$/; +string = 'b\nca'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(145); +pattern = /aa\Z/m; +string = 'ca\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(146); +pattern = /aa\z/m; +string = 'ca\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(147); +pattern = /aa$/m; +string = 'ca\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(148); +pattern = /aa\Z/m; +string = 'b\nca\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(149); +pattern = /aa\z/m; +string = 'b\nca\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(150); +pattern = /aa$/m; +string = 'b\nca\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(151); +pattern = /aa\Z/m; +string = 'b\nca'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(152); +pattern = /aa\z/m; +string = 'b\nca'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(153); +pattern = /aa$/m; +string = 'b\nca'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(154); +pattern = /ab\Z/; +string = 'ab\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(155); +pattern = /ab\z/; +string = 'ab\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(156); +pattern = /ab$/; +string = 'ab\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(157); +pattern = /ab\z/; +string = 'b\nab\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(158); +pattern = /ab\z/m; +string = 'ab\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(159); +pattern = /ab\z/m; +string = 'b\nab\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(160); +pattern = /ab\Z/; +string = 'ac\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(161); +pattern = /ab\z/; +string = 'ac\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(162); +pattern = /ab$/; +string = 'ac\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(163); +pattern = /ab\Z/; +string = 'b\nac\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(164); +pattern = /ab\z/; +string = 'b\nac\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(165); +pattern = /ab$/; +string = 'b\nac\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(166); +pattern = /ab\Z/; +string = 'b\nac'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(167); +pattern = /ab\z/; +string = 'b\nac'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(168); +pattern = /ab$/; +string = 'b\nac'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(169); +pattern = /ab\Z/m; +string = 'ac\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(170); +pattern = /ab\z/m; +string = 'ac\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(171); +pattern = /ab$/m; +string = 'ac\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(172); +pattern = /ab\Z/m; +string = 'b\nac\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(173); +pattern = /ab\z/m; +string = 'b\nac\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(174); +pattern = /ab$/m; +string = 'b\nac\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(175); +pattern = /ab\Z/m; +string = 'b\nac'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(176); +pattern = /ab\z/m; +string = 'b\nac'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(177); +pattern = /ab$/m; +string = 'b\nac'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(178); +pattern = /ab\Z/; +string = 'ca\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(179); +pattern = /ab\z/; +string = 'ca\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(180); +pattern = /ab$/; +string = 'ca\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(181); +pattern = /ab\Z/; +string = 'b\nca\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(182); +pattern = /ab\z/; +string = 'b\nca\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(183); +pattern = /ab$/; +string = 'b\nca\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(184); +pattern = /ab\Z/; +string = 'b\nca'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(185); +pattern = /ab\z/; +string = 'b\nca'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(186); +pattern = /ab$/; +string = 'b\nca'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(187); +pattern = /ab\Z/m; +string = 'ca\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(188); +pattern = /ab\z/m; +string = 'ca\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(189); +pattern = /ab$/m; +string = 'ca\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(190); +pattern = /ab\Z/m; +string = 'b\nca\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(191); +pattern = /ab\z/m; +string = 'b\nca\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(192); +pattern = /ab$/m; +string = 'b\nca\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(193); +pattern = /ab\Z/m; +string = 'b\nca'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(194); +pattern = /ab\z/m; +string = 'b\nca'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(195); +pattern = /ab$/m; +string = 'b\nca'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(196); +pattern = /abb\Z/; +string = 'abb\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(197); +pattern = /abb\z/; +string = 'abb\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(198); +pattern = /abb$/; +string = 'abb\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(199); +pattern = /abb\z/; +string = 'b\nabb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(200); +pattern = /abb\z/m; +string = 'abb\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(201); +pattern = /abb\z/m; +string = 'b\nabb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(202); +pattern = /abb\Z/; +string = 'ac\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(203); +pattern = /abb\z/; +string = 'ac\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(204); +pattern = /abb$/; +string = 'ac\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(205); +pattern = /abb\Z/; +string = 'b\nac\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(206); +pattern = /abb\z/; +string = 'b\nac\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(207); +pattern = /abb$/; +string = 'b\nac\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(208); +pattern = /abb\Z/; +string = 'b\nac'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(209); +pattern = /abb\z/; +string = 'b\nac'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(210); +pattern = /abb$/; +string = 'b\nac'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(211); +pattern = /abb\Z/m; +string = 'ac\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(212); +pattern = /abb\z/m; +string = 'ac\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(213); +pattern = /abb$/m; +string = 'ac\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(214); +pattern = /abb\Z/m; +string = 'b\nac\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(215); +pattern = /abb\z/m; +string = 'b\nac\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(216); +pattern = /abb$/m; +string = 'b\nac\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(217); +pattern = /abb\Z/m; +string = 'b\nac'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(218); +pattern = /abb\z/m; +string = 'b\nac'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(219); +pattern = /abb$/m; +string = 'b\nac'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(220); +pattern = /abb\Z/; +string = 'ca\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(221); +pattern = /abb\z/; +string = 'ca\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(222); +pattern = /abb$/; +string = 'ca\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(223); +pattern = /abb\Z/; +string = 'b\nca\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(224); +pattern = /abb\z/; +string = 'b\nca\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(225); +pattern = /abb$/; +string = 'b\nca\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(226); +pattern = /abb\Z/; +string = 'b\nca'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(227); +pattern = /abb\z/; +string = 'b\nca'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(228); +pattern = /abb$/; +string = 'b\nca'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(229); +pattern = /abb\Z/m; +string = 'ca\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(230); +pattern = /abb\z/m; +string = 'ca\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(231); +pattern = /abb$/m; +string = 'ca\nb\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(232); +pattern = /abb\Z/m; +string = 'b\nca\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(233); +pattern = /abb\z/m; +string = 'b\nca\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(234); +pattern = /abb$/m; +string = 'b\nca\n'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(235); +pattern = /abb\Z/m; +string = 'b\nca'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(236); +pattern = /abb\z/m; +string = 'b\nca'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(237); +pattern = /abb$/m; +string = 'b\nca'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(238); +pattern = /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/; +string = 'x'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(239); +pattern = /\GX.*X/; +string = 'aaaXbX'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(240); +pattern = /\.c(pp|xx|c)?$/i; +string = 'Changes'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(241); +pattern = /^([a-z]:)/; +string = 'C:/'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(242); +pattern = /(\w)?(abc)\1b/; +string = 'abcab'; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +/* ECMA doesn't support (?( + status = inSection(243); + pattern = /^(a)?(?(1)a|b)+$/; + string = 'a'; + actualmatch = string.match(pattern); + expectedmatch = null; + addThis(); +*/ + + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + + +function addThis() +{ + if(omitCurrentSection()) + return; + + statusmessages[i] = status; + patterns[i] = pattern; + strings[i] = string; + actualmatches[i] = actualmatch; + expectedmatches[i] = expectedmatch; + i++; +} + + +function omitCurrentSection() +{ + try + { + // current section number is in global status variable + var n = status.match(/(\d+)/)[1]; + return ((n < cnLBOUND) || (n > cnUBOUND)); + } + catch(e) + { + return false; + } +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + testRegExp(statusmessages, patterns, strings, actualmatches, expectedmatches); +} diff --git a/js/src/tests/non262/RegExp/properties-001.js b/js/src/tests/non262/RegExp/properties-001.js new file mode 100644 index 0000000000..b9cb65e959 --- /dev/null +++ b/js/src/tests/non262/RegExp/properties-001.js @@ -0,0 +1,87 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + * File Name: RegExp/properties-001.js + * ECMA Section: 15.7.6.js + * Description: Based on ECMA 2 Draft 7 February 1999 + * + * Author: christine@netscape.com + * Date: 19 February 1999 + */ +var SECTION = "RegExp/properties-001.js"; +var TITLE = "Properties of RegExp Instances"; + +AddRegExpCases( new RegExp, "(?:)", false, false, false, 0 ); +AddRegExpCases( /.*/, ".*", false, false, false, 0 ); +AddRegExpCases( /[\d]{5}/g, "[\\d]{5}", true, false, false, 0 ); +AddRegExpCases( /[\S]?$/i, "[\\S]?$", false, true, false, 0 ); +AddRegExpCases( /^([a-z]*)[^\w\s\f\n\r]+/m, "^([a-z]*)[^\\w\\s\\f\\n\\r]+", false, false, true, 0 ); +AddRegExpCases( /[\D]{1,5}[\ -][\d]/gi, "[\\D]{1,5}[\\ -][\\d]", true, true, false, 0 ); +AddRegExpCases( /[a-zA-Z0-9]*/gm, "[a-zA-Z0-9]*", true, false, true, 0 ); +AddRegExpCases( /x|y|z/gim, "x|y|z", true, true, true, 0 ); + +AddRegExpCases( /\u0051/im, "\\u0051", false, true, true, 0 ); +AddRegExpCases( /\x45/gm, "\\x45", true, false, true, 0 ); +AddRegExpCases( /\097/gi, "\\097", true, true, false, 0 ); + +test(); + +function AddRegExpCases( re, s, g, i, m, l ) { + + AddTestCase( re + ".test == RegExp.prototype.test", + true, + re.test == RegExp.prototype.test ); + + AddTestCase( re + ".toString == RegExp.prototype.toString", + true, + re.toString == RegExp.prototype.toString ); + + AddTestCase( re + ".contructor == RegExp.prototype.constructor", + true, + re.constructor == RegExp.prototype.constructor ); + + AddTestCase( re + ".compile == RegExp.prototype.compile", + true, + re.compile == RegExp.prototype.compile ); + + AddTestCase( re + ".exec == RegExp.prototype.exec", + true, + re.exec == RegExp.prototype.exec ); + + // properties + + AddTestCase( re + ".source", + s, + re.source ); + +/* + * http://bugzilla.mozilla.org/show_bug.cgi?id=225550 changed + * the behavior of toString() and toSource() on empty regexps. + * So branch if |s| is the empty string - + */ + var S = s? s : '(?:)'; + + AddTestCase( re + ".toString()", + "/" + S +"/" + (g?"g":"") + (i?"i":"") +(m?"m":""), + re.toString() ); + + AddTestCase( re + ".global", + g, + re.global ); + + AddTestCase( re + ".ignoreCase", + i, + re.ignoreCase ); + + AddTestCase( re + ".multiline", + m, + re.multiline); + + AddTestCase( re + ".lastIndex", + l, + re.lastIndex ); +} diff --git a/js/src/tests/non262/RegExp/properties-002.js b/js/src/tests/non262/RegExp/properties-002.js new file mode 100644 index 0000000000..596dce522e --- /dev/null +++ b/js/src/tests/non262/RegExp/properties-002.js @@ -0,0 +1,128 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + * File Name: RegExp/properties-002.js + * ECMA Section: 15.7.6.js + * Description: Based on ECMA 2 Draft 7 February 1999 + * + * Author: christine@netscape.com + * Date: 19 February 1999 + */ +//----------------------------------------------------------------------------- +var SECTION = "RegExp/properties-002.js"; +var TITLE = "Properties of RegExp Instances"; +var BUGNUMBER ="124339"; + +printBugNumber(BUGNUMBER); + +re_1 = /\cA?/g; +re_1.lastIndex = Math.pow(2,31); +AddRegExpCases( re_1, "\\cA?", true, false, false, Math.pow(2,31) ); + +re_2 = /\w*/i; +re_2.lastIndex = Math.pow(2,32) -1; +AddRegExpCases( re_2, "\\w*", false, true, false, Math.pow(2,32)-1 ); + +re_3 = /\*{0,80}/m; +re_3.lastIndex = Math.pow(2,31) -1; +AddRegExpCases( re_3, "\\*{0,80}", false, false, true, Math.pow(2,31) -1 ); + +re_4 = /^./gim; +re_4.lastIndex = Math.pow(2,30) -1; +AddRegExpCases( re_4, "^.", true, true, true, Math.pow(2,30) -1 ); + +re_5 = /\B/; +re_5.lastIndex = Math.pow(2,30); +AddRegExpCases( re_5, "\\B", false, false, false, Math.pow(2,30) ); + +/* + * Brendan: "need to test cases Math.pow(2,32) and greater to see + * whether they round-trip." Reason: thanks to the work done in + * http://bugzilla.mozilla.org/show_bug.cgi?id=124339, lastIndex + * is now stored as a double instead of a uint32_t (unsigned integer). + * + * Note 2^32 -1 is the upper bound for uint32's, but doubles can go + * all the way up to Number.MAX_VALUE. So that's why we need cases + * between those two numbers. + * + */ +re_6 = /\B/; +re_6.lastIndex = Math.pow(2,32); +AddRegExpCases( re_6, "\\B", false, false, false, Math.pow(2,32) ); + +re_7 = /\B/; +re_7.lastIndex = Math.pow(2,32) + 1; +AddRegExpCases( re_7, "\\B", false, false, false, Math.pow(2,32) + 1 ); + +re_8 = /\B/; +re_8.lastIndex = Math.pow(2,32) * 2; +AddRegExpCases( re_8, "\\B", false, false, false, Math.pow(2,32) * 2 ); + +re_9 = /\B/; +re_9.lastIndex = Math.pow(2,40); +AddRegExpCases( re_9, "\\B", false, false, false, Math.pow(2,40) ); + +re_10 = /\B/; +re_10.lastIndex = Number.MAX_VALUE; +AddRegExpCases( re_10, "\\B", false, false, false, Number.MAX_VALUE ); + + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + + +function AddRegExpCases( re, s, g, i, m, l ){ + + AddTestCase( re + ".test == RegExp.prototype.test", + true, + re.test == RegExp.prototype.test ); + + AddTestCase( re + ".toString == RegExp.prototype.toString", + true, + re.toString == RegExp.prototype.toString ); + + AddTestCase( re + ".contructor == RegExp.prototype.constructor", + true, + re.constructor == RegExp.prototype.constructor ); + + AddTestCase( re + ".compile == RegExp.prototype.compile", + true, + re.compile == RegExp.prototype.compile ); + + AddTestCase( re + ".exec == RegExp.prototype.exec", + true, + re.exec == RegExp.prototype.exec ); + + // properties + + AddTestCase( re + ".source", + s, + re.source ); + + AddTestCase( re + ".toString()", + "/" + s +"/" + (g?"g":"") + (i?"i":"") +(m?"m":""), + re.toString() ); + + AddTestCase( re + ".global", + g, + re.global ); + + AddTestCase( re + ".ignoreCase", + i, + re.ignoreCase ); + + AddTestCase( re + ".multiline", + m, + re.multiline); + + AddTestCase( re + ".lastIndex", + l, + re.lastIndex ); +} diff --git a/js/src/tests/non262/RegExp/prototype-different-global.js b/js/src/tests/non262/RegExp/prototype-different-global.js new file mode 100644 index 0000000000..34fc5ee8a1 --- /dev/null +++ b/js/src/tests/non262/RegExp/prototype-different-global.js @@ -0,0 +1,28 @@ +function test(otherGlobal) { + var otherRegExp = otherGlobal.RegExp; + + for (let name of ["global", "ignoreCase", "multiline", "sticky", "unicode", "source"]) { + let getter = Object.getOwnPropertyDescriptor(RegExp.prototype, name).get; + assertEq(typeof getter, "function"); + + // Note: TypeError gets reported from wrong global if cross-compartment, + // so we test both cases. + let ex; + try { + getter.call(otherRegExp.prototype); + } catch (e) { + ex = e; + } + assertEq(ex instanceof TypeError || ex instanceof otherGlobal.TypeError, true); + } + + let flagsGetter = Object.getOwnPropertyDescriptor(RegExp.prototype, "flags").get; + assertEq(flagsGetter.call(otherRegExp.prototype), ""); + + assertEq(RegExp.prototype.toString.call(otherRegExp.prototype), "/(?:)/"); +} +test(newGlobal()); +test(newGlobal({newCompartment: true})); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/RegExp/prototype.js b/js/src/tests/non262/RegExp/prototype.js new file mode 100644 index 0000000000..568608313b --- /dev/null +++ b/js/src/tests/non262/RegExp/prototype.js @@ -0,0 +1,37 @@ +const t = RegExp.prototype; + +let properties = "toString,compile,exec,test," + + "flags,dotAll,global,hasIndices,ignoreCase,multiline,source,sticky,unicode,unicodeSets," + + "constructor," + + "Symbol(Symbol.match),Symbol(Symbol.replace),Symbol(Symbol.search),Symbol(Symbol.split)"; +if (Object.prototype.toSource) { + properties = "toSource," + properties; +} +if (Symbol.matchAll) { + properties += ",Symbol(Symbol.matchAll)"; +} +assertEqArray(Reflect.ownKeys(t).map(String).sort(), properties.split(",").sort()); + + +// Invoking getters on the prototype should not throw +function getter(name) { + return Object.getOwnPropertyDescriptor(t, name).get.call(t); +} + +assertEq(getter("flags"), ""); +assertEq(getter("global"), undefined); +assertEq(getter("ignoreCase"), undefined); +assertEq(getter("multiline"), undefined); +assertEq(getter("source"), "(?:)"); +assertEq(getter("sticky"), undefined); +assertEq(getter("unicode"), undefined); + +assertEq(t.toString(), "/(?:)/"); + +// The methods don't work with the prototype +assertThrowsInstanceOf(() => t.compile("b", "i"), TypeError); +assertThrowsInstanceOf(() => t.test("x"), TypeError); +assertThrowsInstanceOf(() => t.exec("x"), TypeError); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/RegExp/regexp-enumerate-001.js b/js/src/tests/non262/RegExp/regexp-enumerate-001.js new file mode 100644 index 0000000000..a12bd4589a --- /dev/null +++ b/js/src/tests/non262/RegExp/regexp-enumerate-001.js @@ -0,0 +1,79 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + File Name: regexp-enumerate-001.js + ECMA V2 Section: + Description: Regression Test. + + If instance Native Object have properties that are enumerable, + JavaScript enumerated through the properties twice. This only + happened if objects had been instantiated, but their properties + had not been enumerated. ie, the object inherited properties + from its prototype that are enumerated. + + In the core JavaScript, this is only a problem with RegExp + objects, since the inherited properties of most core JavaScript + objects are not enumerated. + + Author: christine@netscape.com, pschwartau@netscape.com + Date: 12 November 1997 + Modified: 14 July 2002 + Reason: See http://bugzilla.mozilla.org/show_bug.cgi?id=155291 + ECMA-262 Ed.3 Sections 15.10.7.1 through 15.10.7.5 + RegExp properties should be DontEnum + * + */ +// onerror = err; + +var SECTION = "regexp-enumerate-001"; +var TITLE = "Regression Test for Enumerating Properties"; + +var BUGNUMBER="339403"; + +printBugNumber(BUGNUMBER); +writeHeaderToLog( SECTION + " "+ TITLE); + +/* + * This test expects RegExp instances to have four enumerated properties: + * source, global, ignoreCase, and lastIndex + * + * 99.01.25: now they also have a multiLine instance property. + * + */ + + +var r = new RegExp(); + +var e = new Array(); + +var t = new TestRegExp(); + +for ( p in r ) { e[e.length] = { property:p, value:r[p] }; t.addProperty( p, r[p]) }; + +new TestCase( "r = new RegExp(); e = new Array(); "+ + "for ( p in r ) { e[e.length] = { property:p, value:r[p] }; e.length", + 0, + e.length ); + +test(); + +function TestRegExp() { + this.addProperty = addProperty; +} +function addProperty(name, value) { + var pass = false; + + if ( eval("this."+name) != void 0 ) { + pass = true; + } else { + eval( "this."+ name+" = "+ false ); + } + + new TestCase( "Property: " + name +" already enumerated?", + false, + pass ); +} diff --git a/js/src/tests/non262/RegExp/regexp-space-character-class.js b/js/src/tests/non262/RegExp/regexp-space-character-class.js new file mode 100644 index 0000000000..a429b54bbd --- /dev/null +++ b/js/src/tests/non262/RegExp/regexp-space-character-class.js @@ -0,0 +1,27 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var gTestfile = 'regexp-space-character-class.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 514808; +var summary = 'Correct space character class in regexes'; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ +printBugNumber(BUGNUMBER); +printStatus (summary); + +// NOTE: White space and line terminators are now tested in +// non262/RegExp/character-class-escape-s.js. + +var non_space_chars = [ "\u200b", "\u200c", "\u200d" ]; + +reportCompare(non_space_chars.some(function(ch){ return /\s/.test(ch); }), false, summary); +} diff --git a/js/src/tests/non262/RegExp/regress-001.js b/js/src/tests/non262/RegExp/regress-001.js new file mode 100644 index 0000000000..163a7a366b --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-001.js @@ -0,0 +1,44 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + * File Name: RegExp/regress-001.js + * ECMA Section: N/A + * Description: Regression test case: + * JS regexp anchoring on empty match bug + * http://bugzilla.mozilla.org/show_bug.cgi?id=2157 + * + * Author: christine@netscape.com + * Date: 19 February 1999 + */ +var SECTION = "RegExp/hex-001.js"; +var TITLE = "JS regexp anchoring on empty match bug"; +var BUGNUMBER = "2157"; + +printBugNumber(BUGNUMBER); + +AddRegExpCases( /a||b/.exec(''), + "/a||b/.exec('')", + 1, + [''] ); + +test(); + +function AddRegExpCases( regexp, str_regexp, length, matches_array ) { + + AddTestCase( + "( " + str_regexp + " ).length", + regexp.length, + regexp.length ); + + + for ( var matches = 0; matches < matches_array.length; matches++ ) { + AddTestCase( + "( " + str_regexp + " )[" + matches +"]", + matches_array[matches], + regexp[matches] ); + } +} diff --git a/js/src/tests/non262/RegExp/regress-100199.js b/js/src/tests/non262/RegExp/regress-100199.js new file mode 100644 index 0000000000..c43665a9a7 --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-100199.js @@ -0,0 +1,271 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Date: 17 September 2001 + * + * SUMMARY: Regression test for Bugzilla bug 100199 + * See http://bugzilla.mozilla.org/show_bug.cgi?id=100199 + * + * The empty character class [] is a valid RegExp construct: the condition + * that a given character belong to a set containing no characters. As such, + * it can never be met and is always FALSE. Similarly, [^] is a condition + * that matches any given character and is always TRUE. + * + * Neither one of these conditions should cause syntax errors in a RegExp. + */ +//----------------------------------------------------------------------------- +var i = 0; +var BUGNUMBER = 100199; +var summary = '[], [^] are valid RegExp conditions. Should not cause errors -'; +var status = ''; +var statusmessages = new Array(); +var pattern = ''; +var patterns = new Array(); +var string = ''; +var strings = new Array(); +var actualmatch = ''; +var actualmatches = new Array(); +var expectedmatch = ''; +var expectedmatches = new Array(); + + +pattern = /[]/; +string = 'abc'; +status = inSection(1); +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +string = ''; +status = inSection(2); +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +string = '['; +status = inSection(3); +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +string = '/'; +status = inSection(4); +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +string = '['; +status = inSection(5); +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +string = ']'; +status = inSection(6); +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +string = '[]'; +status = inSection(7); +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +string = '[ ]'; +status = inSection(8); +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +string = ']['; +status = inSection(9); +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + + +pattern = /a[]/; +string = 'abc'; +status = inSection(10); +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +string = ''; +status = inSection(11); +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +string = 'a['; +status = inSection(12); +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +string = 'a[]'; +status = inSection(13); +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +string = '['; +status = inSection(14); +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +string = ']'; +status = inSection(15); +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +string = '[]'; +status = inSection(16); +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +string = '[ ]'; +status = inSection(17); +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +string = ']['; +status = inSection(18); +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + + +pattern = /[^]/; +string = 'abc'; +status = inSection(19); +actualmatch = string.match(pattern); +expectedmatch = Array('a'); +addThis(); + +string = ''; +status = inSection(20); +actualmatch = string.match(pattern); +expectedmatch = null; //there are no characters to test against the condition +addThis(); + +string = '\/'; +status = inSection(21); +actualmatch = string.match(pattern); +expectedmatch = Array('/'); +addThis(); + +string = '\['; +status = inSection(22); +actualmatch = string.match(pattern); +expectedmatch = Array('['); +addThis(); + +string = '['; +status = inSection(23); +actualmatch = string.match(pattern); +expectedmatch = Array('['); +addThis(); + +string = ']'; +status = inSection(24); +actualmatch = string.match(pattern); +expectedmatch = Array(']'); +addThis(); + +string = '[]'; +status = inSection(25); +actualmatch = string.match(pattern); +expectedmatch = Array('['); +addThis(); + +string = '[ ]'; +status = inSection(26); +actualmatch = string.match(pattern); +expectedmatch = Array('['); +addThis(); + +string = ']['; +status = inSection(27); +actualmatch = string.match(pattern); +expectedmatch = Array(']'); +addThis(); + + +pattern = /a[^]/; +string = 'abc'; +status = inSection(28); +actualmatch = string.match(pattern); +expectedmatch = Array('ab'); +addThis(); + +string = ''; +status = inSection(29); +actualmatch = string.match(pattern); +expectedmatch = null; //there are no characters to test against the condition +addThis(); + +string = 'a['; +status = inSection(30); +actualmatch = string.match(pattern); +expectedmatch = Array('a['); +addThis(); + +string = 'a]'; +status = inSection(31); +actualmatch = string.match(pattern); +expectedmatch = Array('a]'); +addThis(); + +string = 'a[]'; +status = inSection(32); +actualmatch = string.match(pattern); +expectedmatch = Array('a['); +addThis(); + +string = 'a[ ]'; +status = inSection(33); +actualmatch = string.match(pattern); +expectedmatch = Array('a['); +addThis(); + +string = 'a]['; +status = inSection(34); +actualmatch = string.match(pattern); +expectedmatch = Array('a]'); +addThis(); + + + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + + +function addThis() +{ + statusmessages[i] = status; + patterns[i] = pattern; + strings[i] = string; + actualmatches[i] = actualmatch; + expectedmatches[i] = expectedmatch; + i++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + testRegExp(statusmessages, patterns, strings, actualmatches, expectedmatches); +} diff --git a/js/src/tests/non262/RegExp/regress-105972.js b/js/src/tests/non262/RegExp/regress-105972.js new file mode 100644 index 0000000000..ab6d46ba47 --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-105972.js @@ -0,0 +1,121 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Date: 22 October 2001 + * + * SUMMARY: Regression test for Bugzilla bug 105972: + * "/^.*?$/ will not match anything" + * + * See http://bugzilla.mozilla.org/show_bug.cgi?id=105972 + */ +//----------------------------------------------------------------------------- +var i = 0; +var BUGNUMBER = 105972; +var summary = 'Regression test for Bugzilla bug 105972'; +var cnEmptyString = ''; +var status = ''; +var statusmessages = new Array(); +var pattern = ''; +var patterns = new Array(); +var string = ''; +var strings = new Array(); +var actualmatch = ''; +var actualmatches = new Array(); +var expectedmatch = ''; +var expectedmatches = new Array(); + + +/* + * The bug: this match was coming up null in Rhino and SpiderMonkey. + * It should match the whole string. The reason: + * + * The * operator is greedy, but *? is non-greedy: it will stop + * at the simplest match it can find. But the pattern here asks us + * to match till the end of the string. So the simplest match must + * go all the way out to the end, and *? has no choice but to do it. + */ +status = inSection(1); +pattern = /^.*?$/; +string = 'Hello World'; +actualmatch = string.match(pattern); +expectedmatch = Array(string); +addThis(); + + +/* + * Leave off the '$' condition - here we expect the empty string. + * Unlike the above pattern, we don't have to match till the end of + * the string, so the non-greedy operator *? doesn't try to... + */ +status = inSection(2); +pattern = /^.*?/; +string = 'Hello World'; +actualmatch = string.match(pattern); +expectedmatch = Array(cnEmptyString); +addThis(); + + +/* + * Try '$' combined with an 'or' operator. + * + * The operator *? will consume the string from left to right, + * attempting to satisfy the condition (:|$). When it hits ':', + * the match will stop because the operator *? is non-greedy. + * + * The submatch $1 = (:|$) will contain the ':' + */ +status = inSection(3); +pattern = /^.*?(:|$)/; +string = 'Hello: World'; +actualmatch = string.match(pattern); +expectedmatch = Array('Hello:', ':'); +addThis(); + + +/* + * Again, '$' combined with an 'or' operator. + * + * The operator * will consume the string from left to right, + * attempting to satisfy the condition (:|$). When it hits ':', + * the match will not stop since * is greedy. The match will + * continue until it hits $, the end-of-string boundary. + * + * The submatch $1 = (:|$) will contain the empty string + * conceived to exist at the end-of-string boundary. + */ +status = inSection(4); +pattern = /^.*(:|$)/; +string = 'Hello: World'; +actualmatch = string.match(pattern); +expectedmatch = Array(string, cnEmptyString); +addThis(); + + + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + + +function addThis() +{ + statusmessages[i] = status; + patterns[i] = pattern; + strings[i] = string; + actualmatches[i] = actualmatch; + expectedmatches[i] = expectedmatch; + i++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + testRegExp(statusmessages, patterns, strings, actualmatches, expectedmatches); +} diff --git a/js/src/tests/non262/RegExp/regress-119909.js b/js/src/tests/non262/RegExp/regress-119909.js new file mode 100644 index 0000000000..21a8e7750d --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-119909.js @@ -0,0 +1,55 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * + * Date: 14 Jan 2002 + * SUMMARY: Shouldn't crash on regexps with many nested parentheses + * See http://bugzilla.mozilla.org/show_bug.cgi?id=119909 + * + */ +//----------------------------------------------------------------------------- +var BUGNUMBER = 119909; +var summary = "Shouldn't crash on regexps with many nested parentheses"; +var NO_BACKREFS = false; +var DO_BACKREFS = true; + + +//-------------------------------------------------- +test(); +//-------------------------------------------------- + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus(summary); + + testThis(500, NO_BACKREFS, 'hello', 'goodbye'); + testThis(500, DO_BACKREFS, 'hello', 'goodbye'); + + reportCompare('No Crash', 'No Crash', ''); +} + + +/* + * Creates a regexp pattern like (((((((((hello))))))))) + * and tests str.search(), str.match(), str.replace() + */ +function testThis(numParens, doBackRefs, strOriginal, strReplace) +{ + var openParen = doBackRefs? '(' : '(?:'; + var closeParen = ')'; + var pattern = ''; + + for (var i=0; i((.*\n?)*?)<\/body>/i; +actualmatch = string.match(pattern); +expectedmatch = Array(sBody, '\n

Kibology for all

\n

All for Kibology

\n', '

All for Kibology

\n'); +addThis(); + + + +//------------------------------------------------------------------------------------------------- +test(); +//------------------------------------------------------------------------------------------------- + + +function addThis() +{ + statusmessages[i] = status; + patterns[i] = pattern; + strings[i] = string; + actualmatches[i] = actualmatch; + expectedmatches[i] = expectedmatch; + i++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + testRegExp(statusmessages, patterns, strings, actualmatches, expectedmatches); +} diff --git a/js/src/tests/non262/RegExp/regress-169534.js b/js/src/tests/non262/RegExp/regress-169534.js new file mode 100644 index 0000000000..df011f2d32 --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-169534.js @@ -0,0 +1,58 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * + * Date: 20 Sep 2002 + * SUMMARY: RegExp conformance test + * See http://bugzilla.mozilla.org/show_bug.cgi?id=169534 + * + */ +//----------------------------------------------------------------------------- +var UBound = 0; +var BUGNUMBER = 169534; +var summary = 'RegExp conformance test'; +var status = ''; +var statusitems = []; +var actual = ''; +var actualvalues = []; +var expect= ''; +var expectedvalues = []; + + +status = inSection(1); +var re = /(\|)([\w\x81-\xff ]*)(\|)([\/a-z][\w:\/\.]*\.[a-z]{3,4})(\|)/ig; +var str = "To sign up click |here|https://www.xxxx.org/subscribe.htm|"; +actual = str.replace(re, '$2'); +expect = 'To sign up click here'; +addThis(); + + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + + +function addThis() +{ + statusitems[UBound] = status; + actualvalues[UBound] = actual; + expectedvalues[UBound] = expect; + UBound++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus(summary); + + for (var i=0; i/g,'>'); + } + + h+='\n'; + h=h.replace(/&([^\s]+;)/g,'<&$1>'); + h=h.replace(new RegExp('','g'), S); + h=h.replace(/"[^"]*"/g,S); + h=h.replace(/'[^']*'/g,S); + + + h=h.replace(/<([^>]*)>/g, + function(s,p) + { + if(s.match(/!doctype/i)) + return'<' + p + '>'; + + p=p.replace(/\\'/g,'\\'').replace(/\\"/g,'\\"').replace(/^\s/,''); +p=p.replace(/(\s)([^<]+)$/g, + function(s,p1,p2) + { + p2=p2.replace(/(=)(\s*[^"'][^\s]*)(\s|$)/g,'$1$2$3'); + p2=p2.replace(/("[^"]*")/g,'$1'); + p2=p2.replace(/('[^']*')/g,'$1'); + return p1 + ''+p2+''; + } + ) + + return'<' + p + '>'; + } + ) + + + h=h.replace(/<(&[^\s]+;)>/g,'$1'); + h=h.replace(/(<!--[\s\S]*-->)/g,'$1'); + + + numer=1; + h=h.replace(/(.*\n)/g, + function(s,p) + { + return (numer++) +'. ' + p; + } + ) + + + return'' + h + ''; +} + + + +/* + * sanity check + */ +status = inSection(1); +actual = formatHTML('abc'); +expect = '1. abc\n'; +addThis(); + + +/* + * The real test: can we run this without crashing? + * We are not validating the result, just running it. + */ +status = inSection(2); +var HUGE_TEST_STRING = hugeString(); +formatHTML(HUGE_TEST_STRING); + + + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + + +function addThis() +{ + statusitems[UBound] = status; + actualvalues[UBound] = actual; + expectedvalues[UBound] = expect; + UBound++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus(summary); + + for (var i=0; i][^<>]*[^\/])>|<([^\/<>])>/; +string = '

Some
test

'; +actualmatch = string.match(pattern); +expectedmatch = Array('

', undefined, 'p'); +addThis(); + + +//------------------------------------------------------------------------------------------------- +test(); +//------------------------------------------------------------------------------------------------- + + +function addThis() +{ + statusmessages[i] = status; + patterns[i] = pattern; + strings[i] = string; + actualmatches[i] = actualmatch; + expectedmatches[i] = expectedmatch; + i++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + testRegExp(statusmessages, patterns, strings, actualmatches, expectedmatches); +} diff --git a/js/src/tests/non262/RegExp/regress-334158.js b/js/src/tests/non262/RegExp/regress-334158.js new file mode 100644 index 0000000000..a561445536 --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-334158.js @@ -0,0 +1,25 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 334158; +var summary = 'Parse error in control letter escapes (RegExp)'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +expect = true; +actual = /\ca/.test( "\x01" ); +reportCompare(expect, actual, summary + ':/\ca/.test( "\x01" )'); + +expect = false + actual = /\ca/.test( "\\ca" ); +reportCompare(expect, actual, summary + ': /\ca/.test( "\\ca" )'); + +expect = false + actual = /\c[a/]/.test( "\x1ba/]" ); +reportCompare(expect, actual, summary + ': /\c[a/]/.test( "\x1ba/]" )'); diff --git a/js/src/tests/non262/RegExp/regress-346090.js b/js/src/tests/non262/RegExp/regress-346090.js new file mode 100644 index 0000000000..a25c38a563 --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-346090.js @@ -0,0 +1,26 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 346090; +var summary = 'Do not crash with this regexp'; +var actual = 'No Crash'; +var expect = 'No Crash'; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + var r = /%((h[^l]+)|(l[^h]+)){0,2}?a/g; + r.exec('%lld %d'); + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/RegExp/regress-367888.js b/js/src/tests/non262/RegExp/regress-367888.js new file mode 100644 index 0000000000..f303758ca9 --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-367888.js @@ -0,0 +1,26 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 367888; +var summary = 'RegExp /(|)??x/g.exec("y") barfs'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + expect = null; + actual = /(|)??x/g.exec("y"); + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/RegExp/regress-375642.js b/js/src/tests/non262/RegExp/regress-375642.js new file mode 100644 index 0000000000..48cba8fd78 --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-375642.js @@ -0,0 +1,25 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 375642; +var summary = 'RegExp /(?:a??)+?/.exec("")'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + /(?:a??)+?/.exec("") + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/RegExp/regress-375651.js b/js/src/tests/non262/RegExp/regress-375651.js new file mode 100644 index 0000000000..8f3984e875 --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-375651.js @@ -0,0 +1,26 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +//----------------------------------------------------------------------------- +var BUGNUMBER = 375651; +var summary = 'Do not assert with regexp quantifiers'; +var actual = 'No Crash'; +var expect = 'No Crash'; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + /(.{2,3}){0,2}?t/.exec("abt"); + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/RegExp/regress-375711.js b/js/src/tests/non262/RegExp/regress-375711.js new file mode 100644 index 0000000000..4de183691a --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-375711.js @@ -0,0 +1,82 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 375711; +var summary = 'Do not assert with /[Q-b]/i.exec("")'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + var s; + + // see bug 416933 + print('see bug 416933 for changed behavior on Gecko 1.9'); + + try + { + s = '/[Q-b]/.exec("")'; + expect = 'No Error'; + print(s + ' expect ' + expect); + eval(s); + actual = 'No Error'; + } + catch(ex) + { + actual = ex + ''; + } + reportCompare(expect, actual, summary + ': ' + s); + + try + { + s ='/[Q-b]/i.exec("")'; + expect = 'No Error'; + print(s + ' expect ' + expect); + eval(s); + actual = 'No Error'; + } + catch(ex) + { + actual = ex + ''; + } + reportCompare(expect, actual, summary + ': ' + s); + + try + { + s = '/[q-b]/.exec("")'; + expect = 'SyntaxError: invalid range in character class'; + print(s + ' expect ' + expect); + eval(s); + actual = 'No Error'; + } + catch(ex) + { + actual = ex + ''; + } + reportCompare(expect, actual, summary + ': ' + s); + + try + { + s ='/[q-b]/i.exec("")'; + expect = 'SyntaxError: invalid range in character class'; + print(s + ' expect ' + expect); + eval(s); + actual = 'No Error'; + } + catch(ex) + { + actual = ex + ''; + } + reportCompare(expect, actual, summary + ': ' + s); +} diff --git a/js/src/tests/non262/RegExp/regress-375715-01-n.js b/js/src/tests/non262/RegExp/regress-375715-01-n.js new file mode 100644 index 0000000000..dcd003ec17 --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-375715-01-n.js @@ -0,0 +1,27 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 375715; +var summary = 'Do not assert: (c2 <= cs->length) && (c1 <= c2)'; +var actual = ''; +var expect = ''; + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + // note that the assertion does not fire if the regexp is + // evald or used in new RegExp, so this test must be an -n + // with uncaught SyntaxError. + + /[\Wb-G]/.exec(""); + reportCompare(expect, actual, summary + ' /[\Wb-G]/.exec("")'); +} diff --git a/js/src/tests/non262/RegExp/regress-375715-02.js b/js/src/tests/non262/RegExp/regress-375715-02.js new file mode 100644 index 0000000000..9f872cedfc --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-375715-02.js @@ -0,0 +1,24 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 375715; +var summary = 'Do not assert: (c2 <= cs->length) && (c1 <= c2)'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + /[\s-:]/; + reportCompare(expect, actual, summary + '/[\s-:]/'); +} diff --git a/js/src/tests/non262/RegExp/regress-375715-03.js b/js/src/tests/non262/RegExp/regress-375715-03.js new file mode 100644 index 0000000000..112da17df0 --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-375715-03.js @@ -0,0 +1,24 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 375715; +var summary = 'Do not assert: (c2 <= cs->length) && (c1 <= c2)'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + /[_-t]/i.exec(""); + reportCompare(expect, actual, summary + '/[_-t]/i.exec("")'); +} diff --git a/js/src/tests/non262/RegExp/regress-375715-04.js b/js/src/tests/non262/RegExp/regress-375715-04.js new file mode 100644 index 0000000000..8a56c3fe6e --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-375715-04.js @@ -0,0 +1,32 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 375715; +var summary = 'Do not assert: (c2 <= cs->length) && (c1 <= c2)'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + try + { + expect = 'SyntaxError: invalid range in character class'; + (new RegExp("[\xDF-\xC7]]", "i")).exec(""); + } + catch(ex) + { + actual = ex + ''; + } + reportCompare(expect, actual, summary + '(new RegExp("[\xDF-\xC7]]", "i")).exec("")'); +} diff --git a/js/src/tests/non262/RegExp/regress-429241.js b/js/src/tests/non262/RegExp/regress-429241.js new file mode 100644 index 0000000000..a4b588fead --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-429241.js @@ -0,0 +1,200 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var gTestfile = 'regress-429241.js'; +var BUGNUMBER = 429241; +var summary = '\\x or \\u followed by too few hex digits'; +var r; + +reportCompare( + "x", + (r = /[\x]+/.exec("\\x\0")) && r[0], + "Section 1" +); + +reportCompare( + "xy", + (r = /[\xy]+/.exec("\\xy\0")) && r[0], + "Section 2" +); + +reportCompare( + "x0", + (r = /[\x0]+/.exec("\\x0\0")) && r[0], + "Section 3" +); + +reportCompare( + "x0y", + (r = /[\x0y]+/.exec("\\x0y\0")) && r[0], + "Section 4" +); + +reportCompare( + "\0", + (r = /[\x00]+/.exec("\\x\0")) && r[0], + "Section 5" +); + +reportCompare( + "0\0", + (r = /[\x000]+/.exec("0\0")) && r[0], + "Section 6" +); + +reportCompare( + "x", + (r = /^\x$/.exec("x")) && r[0], + "Section 7" +); + +reportCompare( + "xy", + (r = /^\xy$/.exec("xy")) && r[0], + "Section 8" +); + +reportCompare( + "x0", + (r = /^\x0$/.exec("x0")) && r[0], + "Section 9" +); + +reportCompare( + "x0y", + (r = /^\x0y$/.exec("x0y")) && r[0], + "Section 10" +); + +reportCompare( + null, + /^\x00$/.exec("\0" + "0"), + "Section 11" +); + +reportCompare( + "\0" + "0", + (r = /^\x000$/.exec("\0" + "0")) && r[0], + "Section 12" +); + +reportCompare( + "u", + (r = /[\u]+/.exec("\\u\0")) && r[0], + "Section 13" +); + +reportCompare( + "uy", + (r = /[\uy]+/.exec("\\uy\0")) && r[0], + "Section 14" +); + +reportCompare( + "u0", + (r = /[\u0]+/.exec("\\u0\0")) && r[0], + "Section 15" +); + +reportCompare( + "u0", + (r = /[\u00]+/.exec("\\u0\0")) && r[0], + "Section 16" +); + +reportCompare( + "u0", + (r = /[\u000]+/.exec("\\u0\0")) && r[0], + "Section 17" +); + +reportCompare( + "u0y", + (r = /[\u0y]+/.exec("\\u0y\0")) && r[0], + "Section 18" +); + +reportCompare( + "u0y", + (r = /[\u00y]+/.exec("\\u0y\0")) && r[0], + "Section 19" +); + +reportCompare( + "u0y", + (r = /[\u000y]+/.exec("\\u0y\0")) && r[0], + "Section 20" +); + +reportCompare( + "\0", + (r = /[\u0000]+/.exec("\\u\0")) && r[0], + "Section 21" +); + +reportCompare( + "0\0", + (r = /[\u00000]+/.exec("0\0")) && r[0], + "Section 22" +); + +reportCompare( + "u", + (r = /^\u$/.exec("u")) && r[0], + "Section 23" +); + +reportCompare( + "uy", + (r = /^\uy$/.exec("uy")) && r[0], + "Section 24" +); + +reportCompare( + "u0", + (r = /^\u0$/.exec("u0")) && r[0], + "Section 25" +); + +reportCompare( + "u00", + (r = /^\u00$/.exec("u00")) && r[0], + "Section 26" +); + +reportCompare( + "u000", + (r = /^\u000$/.exec("u000")) && r[0], + "Section 27" +); + +reportCompare( + "u0y", + (r = /^\u0y$/.exec("u0y")) && r[0], + "Section 28" +); + +reportCompare( + "u00y", + (r = /^\u00y$/.exec("u00y")) && r[0], + "Section 29" +); + +reportCompare( + "u000y", + (r = /^\u000y$/.exec("u000y")) && r[0], + "Section 30" +); + +reportCompare( + null, + /^\u0000$/.exec("\0" + "0"), + "Section 31" +); + +reportCompare( + "\0" + "0", + (r = /^\u00000$/.exec("\0" + "0")) && r[0], + "Section 32" +); diff --git a/js/src/tests/non262/RegExp/regress-436700.js b/js/src/tests/non262/RegExp/regress-436700.js new file mode 100644 index 0000000000..f5991cdae8 --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-436700.js @@ -0,0 +1,31 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 436700; +var summary = 'Do not assert: 1 <= num && num <= 0x10000'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + try + { + /\2147483648/.exec(String.fromCharCode(140) + "7483648").toString(); + } + catch(ex) + { + } + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/RegExp/regress-465862.js b/js/src/tests/non262/RegExp/regress-465862.js new file mode 100644 index 0000000000..cb1cfe10f5 --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-465862.js @@ -0,0 +1,80 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465862; +var summary = 'Do case-insensitive matching correctly in JIT for non-ASCII-letters'; + +var i = 0; +var status = ''; +var statusmessages = new Array(); +var pattern = ''; +var patterns = new Array(); +var string = ''; +var strings = new Array(); +var actualmatch = ''; +var actualmatches = new Array(); +var expectedmatch = ''; +var expectedmatches = new Array(); + +// Note: we must call the RegExp constructor here instead of using +// literals. Otherwise, because the regexps are compiled at parse +// time, they will not be compiled to native code and we will not +// actually be testing jitted regexps. + + +status = inSection(1); +string = '@'; +pattern = new RegExp('@', 'i'); +actualmatch = string.match(pattern); +expectedmatch = Array(string); +addThis(); + +status = inSection(2); +string = '`'; +pattern = new RegExp('`', 'i'); +actualmatch = string.match(pattern); +expectedmatch = Array(string); +addThis(); + +status = inSection(3); +string = '@'; +pattern = new RegExp('`', 'i'); +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(4); +string = '`'; +pattern = new RegExp('@', 'i'); +print(string + ' ' + pattern); +actualmatch = string.match(pattern); +print('z ' + actualmatch); +print('`'.match(/@/i)); +expectedmatch = null; +addThis(); + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function addThis() +{ + statusmessages[i] = status; + patterns[i] = pattern; + strings[i] = string; + actualmatches[i] = actualmatch; + expectedmatches[i] = expectedmatch; + i++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + testRegExp(statusmessages, patterns, strings, actualmatches, expectedmatches); +} diff --git a/js/src/tests/non262/RegExp/regress-57572.js b/js/src/tests/non262/RegExp/regress-57572.js new file mode 100644 index 0000000000..373f69191b --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-57572.js @@ -0,0 +1,114 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Date: 28 December 2000 + * + * SUMMARY: Testing regular expressions containing the ? character. + * Arose from Bugzilla bug 57572: "RegExp with ? matches incorrectly" + * + * See http://bugzilla.mozilla.org/show_bug.cgi?id=57572 + * + */ +//----------------------------------------------------------------------------- +var i = 0; +var BUGNUMBER = 57572; +var summary = 'Testing regular expressions containing "?"'; +var cnEmptyString = ''; var cnSingleSpace = ' '; +var status = ''; +var statusmessages = new Array(); +var pattern = ''; +var patterns = new Array(); +var string = ''; +var strings = new Array(); +var actualmatch = ''; +var actualmatches = new Array(); +var expectedmatch = ''; +var expectedmatches = new Array(); + + +status = inSection(1); +pattern = /(\S+)?(.*)/; +string = 'Test this'; +actualmatch = string.match(pattern); +expectedmatch = Array(string, 'Test', ' this'); //single space in front of 'this' +addThis(); + +status = inSection(2); +pattern = /(\S+)? ?(.*)/; //single space between the ? characters +string= 'Test this'; +actualmatch = string.match(pattern); +expectedmatch = Array(string, 'Test', 'this'); //NO space in front of 'this' +addThis(); + +status = inSection(3); +pattern = /(\S+)?(.*)/; +string = 'Stupid phrase, with six - (short) words'; +actualmatch = string.match(pattern); +expectedmatch = Array(string, 'Stupid', ' phrase, with six - (short) words'); //single space in front of 'phrase' +addThis(); + +status = inSection(4); +pattern = /(\S+)? ?(.*)/; //single space between the ? characters +string = 'Stupid phrase, with six - (short) words'; +actualmatch = string.match(pattern); +expectedmatch = Array(string, 'Stupid', 'phrase, with six - (short) words'); //NO space in front of 'phrase' +addThis(); + + +// let's add an extra back-reference this time - three instead of two - +status = inSection(5); +pattern = /(\S+)?( ?)(.*)/; //single space before second ? character +string = 'Stupid phrase, with six - (short) words'; +actualmatch = string.match(pattern); +expectedmatch = Array(string, 'Stupid', cnSingleSpace, 'phrase, with six - (short) words'); +addThis(); + +status = inSection(6); +pattern = /^(\S+)?( ?)(B+)$/; //single space before second ? character +string = 'AAABBB'; +actualmatch = string.match(pattern); +expectedmatch = Array(string, 'AAABB', cnEmptyString, 'B'); +addThis(); + +status = inSection(7); +pattern = /(\S+)?(!?)(.*)/; +string = 'WOW !!! !!!'; +actualmatch = string.match(pattern); +expectedmatch = Array(string, 'WOW', cnEmptyString, ' !!! !!!'); +addThis(); + +status = inSection(8); +pattern = /(.+)?(!?)(!+)/; +string = 'WOW !!! !!!'; +actualmatch = string.match(pattern); +expectedmatch = Array(string, 'WOW !!! !!', cnEmptyString, '!'); +addThis(); + + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + + +function addThis() +{ + statusmessages[i] = status; + patterns[i] = pattern; + strings[i] = string; + actualmatches[i] = actualmatch; + expectedmatches[i] = expectedmatch; + i++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + testRegExp(statusmessages, patterns, strings, actualmatches, expectedmatches); +} diff --git a/js/src/tests/non262/RegExp/regress-57631.js b/js/src/tests/non262/RegExp/regress-57631.js new file mode 100644 index 0000000000..eb598d2e7d --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-57631.js @@ -0,0 +1,115 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Date: 26 November 2000 + * + * + * SUMMARY: This test arose from Bugzilla bug 57631: + * "RegExp with invalid pattern or invalid flag causes segfault" + * + * Either error should throw an exception of type SyntaxError, + * and we check to see that it does... + */ +//----------------------------------------------------------------------------- +var BUGNUMBER = '57631'; +var summary = 'Testing new RegExp(pattern,flag) with illegal pattern or flag'; +var statprefix = 'Testing for error creating illegal RegExp object on pattern '; +var statsuffix = 'and flag '; +var cnSUCCESS = 'SyntaxError'; +var cnFAILURE = 'not a SyntaxError'; +var singlequote = "'"; +var i = -1; var j = -1; var s = ''; var f = ''; +var obj = {}; +var status = ''; var actual = ''; var expect = ''; var msg = ''; +var legalpatterns = new Array(); var illegalpatterns = new Array(); +var legalflags = new Array(); var illegalflags = new Array(); + + +// valid regular expressions to try - +legalpatterns[0] = ''; +legalpatterns[1] = 'abc'; +legalpatterns[2] = '(.*)(3-1)\s\w'; +legalpatterns[3] = '(.*)(...)\\s\\w'; +legalpatterns[4] = '[^A-Za-z0-9_]'; +legalpatterns[5] = '[^\f\n\r\t\v](123.5)([4 - 8]$)'; + +// invalid regular expressions to try - +illegalpatterns[0] = '(?)'; +illegalpatterns[1] = '(a'; +illegalpatterns[2] = '( ]'; +//illegalpatterns[3] = '\d{1,s}'; + +// valid flags to try - +legalflags[0] = 'i'; +legalflags[1] = 'g'; +legalflags[2] = 'm'; +legalflags[3] = undefined; + +// invalid flags to try - +illegalflags[0] = 'a'; +illegalflags[1] = 123; +illegalflags[2] = new RegExp(); + + + +//------------------------------------------------------------------------------------------------- +test(); +//------------------------------------------------------------------------------------------------- + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + testIllegalRegExps(legalpatterns, illegalflags); + testIllegalRegExps(illegalpatterns, legalflags); + testIllegalRegExps(illegalpatterns, illegalflags); +} + + +// This function will only be called where all the patterns are illegal, or all the flags +function testIllegalRegExps(patterns, flags) +{ + for (i in patterns) + { + s = patterns[i]; + + for (j in flags) + { + f = flags[j]; + status = getStatus(s, f); + actual = cnFAILURE; + expect = cnSUCCESS; + + try + { + // This should cause an exception if either s or f is illegal - + eval('obj = new RegExp(s, f);'); + } + catch(e) + { + // We expect to get a SyntaxError - test for this: + if (e instanceof SyntaxError) + actual = cnSUCCESS; + } + + reportCompare(expect, actual, status); + } + } +} + + +function getStatus(regexp, flag) +{ + return (statprefix + quote(regexp) + statsuffix + quote(flag)); +} + + +function quote(text) +{ + return (singlequote + text + singlequote); +} diff --git a/js/src/tests/non262/RegExp/regress-576828.js b/js/src/tests/non262/RegExp/regress-576828.js new file mode 100644 index 0000000000..45e97dc3b1 --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-576828.js @@ -0,0 +1,8 @@ +var re = /(z\1){3}/; +var str = 'zzz'; +var actual = re.exec(str); +var expected = makeExpectedMatch(['zzz', 'z'], 0, str); +checkRegExpMatch(actual, expected); + +if (typeof reportCompare == 'function') + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/regress-613820-1.js b/js/src/tests/non262/RegExp/regress-613820-1.js new file mode 100644 index 0000000000..e5e755b24a --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-613820-1.js @@ -0,0 +1,9 @@ +/* Back reference is actually a forwards reference. */ +var re = /(\2(a)){2}/; +var str = 'aaa'; +var actual = re.exec(str); +var expected = makeExpectedMatch(['aa', 'a', 'a'], 0, str); +checkRegExpMatch(actual, expected); + +if (typeof reportCompare === 'function') + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/regress-613820-2.js b/js/src/tests/non262/RegExp/regress-613820-2.js new file mode 100644 index 0000000000..5db7244ba2 --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-613820-2.js @@ -0,0 +1,9 @@ +/* Resetting of inner capture groups across quantified capturing parens. */ +var re = /(?:(f)(o)(o)|(b)(a)(r))*/; +var str = 'foobar'; +var actual = re.exec(str); +var expected = makeExpectedMatch(['foobar', undefined, undefined, undefined, 'b', 'a', 'r'], 0, str); +checkRegExpMatch(actual, expected); + +if (typeof reportCompare === 'function') + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/regress-613820-3.js b/js/src/tests/non262/RegExp/regress-613820-3.js new file mode 100644 index 0000000000..126e838ff2 --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-613820-3.js @@ -0,0 +1,9 @@ +/* Capture group reset to undefined during second iteration, so backreference doesn't see prior result. */ +var re = /(?:^(a)|\1(a)|(ab)){2}/; +var str = 'aab'; +var actual = re.exec(str); +var expected = makeExpectedMatch(['aa', undefined, 'a', undefined], 0, str); +checkRegExpMatch(actual, expected); + +if (typeof reportCompare === 'function') + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/regress-617935.js b/js/src/tests/non262/RegExp/regress-617935.js new file mode 100644 index 0000000000..3764d81b0e --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-617935.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(!xulRuntime.shell&&(Android||xulRuntime.OS=="WINNT")) silentfail +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * + * Author: Christian Holler + */ + +expectExitCode(0); +expectExitCode(5); + +/* Length of 32 */ +var foo = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + +/* Make len(foo) 32768 */ +for (i = 0; i < 10; ++i) { + foo += foo; +} + +/* Add one "a" to cause overflow later */ +foo += "a"; + +var bar = "bbbbbbbbbbbbbbbb"; + +/* Make len(bar) 8192 */ +for (i = 0; i < 9; ++i) { + bar += bar; +} + +/* + * Resulting string should be + * len(foo) * len(bar) = (2**10 * 32 + 1) * 8192 = 268443648 + * which will be larger than the max string length (2**28, or 268435456). + */ +try { + foo.replace(/[a]/g, bar); +} catch (e) { + reportCompare(e instanceof InternalError, true, "Internal error due to overallocation is ok."); +} +reportCompare(true, true, "No crash occurred."); + +print("Tests complete"); diff --git a/js/src/tests/non262/RegExp/regress-6359.js b/js/src/tests/non262/RegExp/regress-6359.js new file mode 100644 index 0000000000..fae056fa53 --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-6359.js @@ -0,0 +1,52 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + * File Name: regress-6359.js + * Reference: ** replace with bugzilla URL or document reference ** + * Description: ** replace with description of test ** + * Author: ** replace with your e-mail address ** + */ + +var SECTION = "js1_2"; // provide a document reference (ie, ECMA section) +var TITLE = "Regression test for bugzilla # 6359"; // Provide ECMA section title or a description +var BUGNUMBER = "http://bugzilla.mozilla.org/show_bug.cgi?id=6359"; // Provide URL to bugsplat or bugzilla report + +printBugNumber(BUGNUMBER); + +/* + * Calls to AddTestCase here. AddTestCase is a function that is defined + * in shell.js and takes three arguments: + * - a string representation of what is being tested + * - the expected result + * - the actual result + * + * For example, a test might look like this: + * + * var zip = /[\d]{5}$/; + * + * AddTestCase( + * "zip = /[\d]{5}$/; \"PO Box 12345 Boston, MA 02134\".match(zip)", // description of the test + * "02134", // expected result + * "PO Box 12345 Boston, MA 02134".match(zip) ); // actual result + * + */ + +AddTestCase( '/(a*)b\1+/.exec("baaac").length', + 2, + /(a*)b\1+/.exec("baaac").length ); + +AddTestCase( '/(a*)b\1+/.exec("baaac")[0]', + "b", + /(a*)b\1+/.exec("baaac")[0]); + +AddTestCase( '/(a*)b\1+/.exec("baaac")[1]', + "", + /(a*)b\1+/.exec("baaac")[1]); + + +test(); // leave this alone. this executes the test cases and +// displays results. diff --git a/js/src/tests/non262/RegExp/regress-67773.js b/js/src/tests/non262/RegExp/regress-67773.js new file mode 100644 index 0000000000..1df7680d0f --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-67773.js @@ -0,0 +1,175 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Date: 06 February 2001 + * + * SUMMARY: Arose from Bugzilla bug 67773: + * "Regular subexpressions followed by + failing to run to completion" + * + * See http://bugzilla.mozilla.org/show_bug.cgi?id=67773 + * See http://bugzilla.mozilla.org/show_bug.cgi?id=69989 + */ +//----------------------------------------------------------------------------- +var i = 0; +var BUGNUMBER = 67773; +var summary = 'Testing regular subexpressions followed by ? or +\n'; +var cnSingleSpace = ' '; +var status = ''; +var statusmessages = new Array(); +var pattern = ''; +var patterns = new Array(); +var string = ''; +var strings = new Array(); +var actualmatch = ''; +var actualmatches = new Array(); +var expectedmatch = ''; +var expectedmatches = new Array(); + + +pattern = /^(\S+)?( ?)(B+)$/; //single space before second ? character +status = inSection(1); +string = 'AAABBB AAABBB '; //single space at middle and at end - +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(2); +string = 'AAABBB BBB'; //single space in the middle +actualmatch = string.match(pattern); +expectedmatch = Array(string, 'AAABBB', cnSingleSpace, 'BBB'); +addThis(); + +status = inSection(3); +string = 'AAABBB AAABBB'; //single space in the middle +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + + +pattern = /^(A+B)+$/; +status = inSection(4); +string = 'AABAAB'; +actualmatch = string.match(pattern); +expectedmatch = Array(string, 'AAB'); +addThis(); + +status = inSection(5); +string = 'ABAABAAAAAAB'; +actualmatch = string.match(pattern); +expectedmatch = Array(string, 'AAAAAAB'); +addThis(); + +status = inSection(6); +string = 'ABAABAABAB'; +actualmatch = string.match(pattern); +expectedmatch = Array(string, 'AB'); +addThis(); + +status = inSection(7); +string = 'ABAABAABABB'; +actualmatch = string.match(pattern); +expectedmatch = null; // because string doesn't match at end +addThis(); + + +pattern = /^(A+1)+$/; +status = inSection(8); +string = 'AA1AA1'; +actualmatch = string.match(pattern); +expectedmatch = Array(string, 'AA1'); +addThis(); + + +pattern = /^(\w+\-)+$/; +status = inSection(9); +string = ''; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(10); +string = 'bla-'; +actualmatch = string.match(pattern); +expectedmatch = Array(string, string); +addThis(); + +status = inSection(11); +string = 'bla-bla'; // hyphen missing at end - +actualmatch = string.match(pattern); +expectedmatch = null; //because string doesn't match at end +addThis(); + +status = inSection(12); +string = 'bla-bla-'; +actualmatch = string.match(pattern); +expectedmatch = Array(string, 'bla-'); +addThis(); + + +pattern = /^(\S+)+(A+)$/; +status = inSection(13); +string = 'asdldflkjAAA'; +actualmatch = string.match(pattern); +expectedmatch = Array(string, 'asdldflkjAA', 'A'); +addThis(); + +status = inSection(14); +string = 'asdldflkj AAA'; // space in middle +actualmatch = string.match(pattern); +expectedmatch = null; //because of the space +addThis(); + + +pattern = /^(\S+)+(\d+)$/; +status = inSection(15); +string = 'asdldflkj122211'; +actualmatch = string.match(pattern); +expectedmatch = Array(string, 'asdldflkj12221', '1'); +addThis(); + +status = inSection(16); +string = 'asdldflkj1111111aaa1'; +actualmatch = string.match(pattern); +expectedmatch = Array(string, 'asdldflkj1111111aaa', '1'); +addThis(); + + +/* + * This one comes from Stephen Ostermiller. + * See http://bugzilla.mozilla.org/show_bug.cgi?id=69989 + */ +pattern = /^[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)+$/; +status = inSection(17); +string = 'some.host.tld'; +actualmatch = string.match(pattern); +expectedmatch = Array(string, '.tld', '.'); +addThis(); + + + +//------------------------------------------------------------------------------------------------- +test(); +//------------------------------------------------------------------------------------------------- + + + +function addThis() +{ + statusmessages[i] = status; + patterns[i] = pattern; + strings[i] = string; + actualmatches[i] = actualmatch; + expectedmatches[i] = expectedmatch; + i++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + testRegExp(statusmessages, patterns, strings, actualmatches, expectedmatches); +} diff --git a/js/src/tests/non262/RegExp/regress-72964.js b/js/src/tests/non262/RegExp/regress-72964.js new file mode 100644 index 0000000000..70ca502ff1 --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-72964.js @@ -0,0 +1,85 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Date: 2001-07-17 + * + * SUMMARY: Regression test for Bugzilla bug 72964: + * "String method for pattern matching failed for Chinese Simplified (GB2312)" + * + * See http://bugzilla.mozilla.org/show_bug.cgi?id=72964 + */ +//----------------------------------------------------------------------------- +var i = 0; +var BUGNUMBER = 72964; +var summary = 'Testing regular expressions containing non-Latin1 characters'; +var cnSingleSpace = ' '; +var status = ''; +var statusmessages = new Array(); +var pattern = ''; +var patterns = new Array(); +var string = ''; +var strings = new Array(); +var actualmatch = ''; +var actualmatches = new Array(); +var expectedmatch = ''; +var expectedmatches = new Array(); + + +pattern = /[\S]+/; +// 4 low Unicode chars = Latin1; whole string should match +status = inSection(1); +string = '\u00BF\u00CD\u00BB\u00A7'; +actualmatch = string.match(pattern); +expectedmatch = Array(string); +addThis(); + +// Now put a space in the middle; first half of string should match +status = inSection(2); +string = '\u00BF\u00CD \u00BB\u00A7'; +actualmatch = string.match(pattern); +expectedmatch = Array('\u00BF\u00CD'); +addThis(); + + +// 4 high Unicode chars = non-Latin1; whole string should match +status = inSection(3); +string = '\u4e00\uac00\u4e03\u4e00'; +actualmatch = string.match(pattern); +expectedmatch = Array(string); +addThis(); + +// Now put a space in the middle; first half of string should match +status = inSection(4); +string = '\u4e00\uac00 \u4e03\u4e00'; +actualmatch = string.match(pattern); +expectedmatch = Array('\u4e00\uac00'); +addThis(); + + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + + +function addThis() +{ + statusmessages[i] = status; + patterns[i] = pattern; + strings[i] = string; + actualmatches[i] = actualmatch; + expectedmatches[i] = expectedmatch; + i++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + testRegExp(statusmessages, patterns, strings, actualmatches, expectedmatches); +} diff --git a/js/src/tests/non262/RegExp/regress-76683.js b/js/src/tests/non262/RegExp/regress-76683.js new file mode 100644 index 0000000000..ff839bb0ca --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-76683.js @@ -0,0 +1,78 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Date: 01 May 2001 + * + * SUMMARY: Regression test for Bugzilla bug 76683 on Rhino: + * "RegExp regression (NullPointerException)" + * + * See http://bugzilla.mozilla.org/show_bug.cgi?id=76683 + */ +//----------------------------------------------------------------------------- +var i = 0; +var BUGNUMBER = 76683; +var summary = 'Regression test for Bugzilla bug 76683'; +var status = ''; +var statusmessages = new Array(); +var pattern = ''; +var patterns = new Array(); +var string = ''; +var strings = new Array(); +var actualmatch = ''; +var actualmatches = new Array(); +var expectedmatch = ''; +var expectedmatches = new Array(); + + +/* + * Rhino (2001-04-19) crashed on the 3rd regular expression below. + * It didn't matter what the string was. No problem in SpiderMonkey - + */ +string = 'abc'; +status = inSection(1); +pattern = /()|(<([\$\w:\.\-]+)((([ ][^\/>]*)?\/>)|(([ ][^>]*)?>)))/; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +status = inSection(2); +pattern = /()|(<(tagPattern)((([ ][^\/>]*)?\/>)|(([ ][^>]*)?>)))/; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + +// This was the one causing a Rhino crash - +status = inSection(3); +pattern = /()|(<(tagPattern)((([ ][^\/>]*)?\/>)|(([ ][^>]*)?>)))|(<\/tagPattern[^>]*>)/; +actualmatch = string.match(pattern); +expectedmatch = null; +addThis(); + + + +//------------------------------------------------------------------------------------------------- +test(); +//------------------------------------------------------------------------------------------------- + + + +function addThis() +{ + statusmessages[i] = status; + patterns[i] = pattern; + strings[i] = string; + actualmatches[i] = actualmatch; + expectedmatches[i] = expectedmatch; + i++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + testRegExp(statusmessages, patterns, strings, actualmatches, expectedmatches); +} diff --git a/js/src/tests/non262/RegExp/regress-78156.js b/js/src/tests/non262/RegExp/regress-78156.js new file mode 100644 index 0000000000..01ef647638 --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-78156.js @@ -0,0 +1,87 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Date: 06 February 2001 + * + * SUMMARY: Arose from Bugzilla bug 78156: + * "m flag of regular expression does not work with $" + * + * See http://bugzilla.mozilla.org/show_bug.cgi?id=78156 + * + * The m flag means a regular expression should search strings + * across multiple lines, i.e. across '\n', '\r'. + */ +//----------------------------------------------------------------------------- +var i = 0; +var BUGNUMBER = 78156; +var summary = 'Testing regular expressions with ^, $, and the m flag -'; +var status = ''; +var statusmessages = new Array(); +var pattern = ''; +var patterns = new Array(); +var string = ''; +var strings = new Array(); +var actualmatch = ''; +var actualmatches = new Array(); +var expectedmatch = ''; +var expectedmatches = new Array(); + +/* + * All patterns have an m flag; all strings are multiline. + * Looking for digit characters at beginning/end of lines. + */ + +string = 'aaa\n789\r\nccc\r\n345'; +status = inSection(1); +pattern = /^\d/gm; +actualmatch = string.match(pattern); +expectedmatch = ['7','3']; +addThis(); + +status = inSection(2); +pattern = /\d$/gm; +actualmatch = string.match(pattern); +expectedmatch = ['9','5']; +addThis(); + +string = 'aaa\n789\r\nccc\r\nddd'; +status = inSection(3); +pattern = /^\d/gm; +actualmatch = string.match(pattern); +expectedmatch = ['7']; +addThis(); + +status = inSection(4); +pattern = /\d$/gm; +actualmatch = string.match(pattern); +expectedmatch = ['9']; +addThis(); + + + +//------------------------------------------------------------------------------------------------- +test(); +//------------------------------------------------------------------------------------------------- + + + +function addThis() +{ + statusmessages[i] = status; + patterns[i] = pattern; + strings[i] = string; + actualmatches[i] = actualmatch; + expectedmatches[i] = expectedmatch; + i++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + testRegExp(statusmessages, patterns, strings, actualmatches, expectedmatches); +} diff --git a/js/src/tests/non262/RegExp/regress-87231.js b/js/src/tests/non262/RegExp/regress-87231.js new file mode 100644 index 0000000000..9d5adaedeb --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-87231.js @@ -0,0 +1,109 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Date: 22 June 2001 + * + * SUMMARY: Regression test for Bugzilla bug 87231: + * "Regular expression /(A)?(A.*)/ picks 'A' twice" + * + * See http://bugzilla.mozilla.org/show_bug.cgi?id=87231 + * Key case: + * + * pattern = /^(A)?(A.*)$/; + * string = 'A'; + * expectedmatch = Array('A', '', 'A'); + * + * + * We expect the 1st subexpression (A)? NOT to consume the single 'A'. + * Recall that "?" means "match 0 or 1 times". Here, it should NOT do + * greedy matching: it should match 0 times instead of 1. This allows + * the 2nd subexpression to make the only match it can: the single 'A'. + * Such "altruism" is the only way there can be a successful global match... + */ +//----------------------------------------------------------------------------- +var i = 0; +var BUGNUMBER = 87231; +var cnEmptyString = ''; +var summary = 'Testing regular expression /(A)?(A.*)/'; +var status = ''; +var statusmessages = new Array(); +var pattern = ''; +var patterns = new Array(); +var string = ''; +var strings = new Array(); +var actualmatch = ''; +var actualmatches = new Array(); +var expectedmatch = ''; +var expectedmatches = new Array(); + + +pattern = /^(A)?(A.*)$/; +status = inSection(1); +string = 'AAA'; +actualmatch = string.match(pattern); +expectedmatch = Array('AAA', 'A', 'AA'); +addThis(); + +status = inSection(2); +string = 'AA'; +actualmatch = string.match(pattern); +expectedmatch = Array('AA', 'A', 'A'); +addThis(); + +status = inSection(3); +string = 'A'; +actualmatch = string.match(pattern); +expectedmatch = Array('A', undefined, 'A'); // 'altruistic' case: see above +addThis(); + + +pattern = /(A)?(A.*)/; +var strL = 'zxcasd;fl\\\ ^'; +var strR = 'aaAAaaaf;lrlrzs'; + +status = inSection(4); +string = strL + 'AAA' + strR; +actualmatch = string.match(pattern); +expectedmatch = Array('AAA' + strR, 'A', 'AA' + strR); +addThis(); + +status = inSection(5); +string = strL + 'AA' + strR; +actualmatch = string.match(pattern); +expectedmatch = Array('AA' + strR, 'A', 'A' + strR); +addThis(); + +status = inSection(6); +string = strL + 'A' + strR; +actualmatch = string.match(pattern); +expectedmatch = Array('A' + strR, undefined, 'A' + strR); // 'altruistic' case: see above +addThis(); + + + +//------------------------------------------------------------------------------------------------- +test(); +//------------------------------------------------------------------------------------------------- + + + +function addThis() +{ + statusmessages[i] = status; + patterns[i] = pattern; + strings[i] = string; + actualmatches[i] = actualmatch; + expectedmatches[i] = expectedmatch; + i++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + testRegExp(statusmessages, patterns, strings, actualmatches, expectedmatches); +} diff --git a/js/src/tests/non262/RegExp/regress-9141.js b/js/src/tests/non262/RegExp/regress-9141.js new file mode 100644 index 0000000000..b95e40aaa1 --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-9141.js @@ -0,0 +1,71 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + + +/** + * File Name: regress-9141.js + * Reference: "http://bugzilla.mozilla.org/show_bug.cgi?id=9141"; + * Description: + * From waldemar@netscape.com: + * + * The following page crashes the system: + * + * + * + * + * + * + * + * + */ + +var SECTION = "js1_2"; // provide a document reference (ie, ECMA section) +var TITLE = "Regression test for bugzilla # 9141"; // Provide ECMA section title or a description +var BUGNUMBER = "http://bugzilla.mozilla.org/show_bug.cgi?id=9141"; // Provide URL to bugsplat or bugzilla report + +printBugNumber(BUGNUMBER); + +/* + * Calls to AddTestCase here. AddTestCase is a function that is defined + * in shell.js and takes three arguments: + * - a string representation of what is being tested + * - the expected result + * - the actual result + * + * For example, a test might look like this: + * + * var zip = /[\d]{5}$/; + * + * AddTestCase( + * "zip = /[\d]{5}$/; \"PO Box 12345 Boston, MA 02134\".match(zip)", // description of the test + * "02134", // expected result + * "PO Box 12345 Boston, MA 02134".match(zip) ); // actual result + * + */ + +var s = "x"; +for (var i = 0; i != 13; i++) s += s; +var a = /(?:xx|x)*/.exec(s); +var b = /(xx|x)*/.exec(s); + +AddTestCase( "var s = 'x'; for (var i = 0; i != 13; i++) s += s; " + + "a = /(?:xx|x)*/.exec(s); a.length", + 1, + a.length ); + +AddTestCase( "var b = /(xx|x)*/.exec(s); b.length", + 2, + b.length ); + +test(); // leave this alone. this executes the test cases and +// displays results. diff --git a/js/src/tests/non262/RegExp/regress-98306.js b/js/src/tests/non262/RegExp/regress-98306.js new file mode 100644 index 0000000000..261f0de316 --- /dev/null +++ b/js/src/tests/non262/RegExp/regress-98306.js @@ -0,0 +1,63 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Date: 04 September 2001 + * + * SUMMARY: Regression test for Bugzilla bug 98306 + * "JS parser crashes in ParseAtom for script using Regexp()" + * + * See http://bugzilla.mozilla.org/show_bug.cgi?id=98306 + */ +//----------------------------------------------------------------------------- +var BUGNUMBER = 98306; +var summary = "Testing that we don't crash on this code -"; +var cnUBOUND = 10; +var re; +var s; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + s = '"Hello".match(/[/]/)'; + tryThis(s); + + s = 're = /[/'; + tryThis(s); + + s = 're = /[/]/'; + tryThis(s); + + s = 're = /[//]/'; + tryThis(s); + + reportCompare('No Crash', 'No Crash', ''); +} + + +// Try to provoke a crash - +function tryThis(sCode) +{ + // sometimes more than one attempt is necessary - + for (var i=0; i null; + } +}); + +var rx = RegExp("a", "g"); +var s = "abba"; +var r = rx[Symbol.replace](s, "c"); +assertEq(r, "abba"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/replace-local-tolength-lastindex.js b/js/src/tests/non262/RegExp/replace-local-tolength-lastindex.js new file mode 100644 index 0000000000..7ba840e000 --- /dev/null +++ b/js/src/tests/non262/RegExp/replace-local-tolength-lastindex.js @@ -0,0 +1,22 @@ +// RegExp.prototype[@@replace] always executes ToLength(regExp.lastIndex) for +// non-global RegExps. + +for (var flag of ["", "g", "y", "gy"]) { + var regExp = new RegExp("a", flag); + + var called = false; + regExp.lastIndex = { + valueOf() { + assertEq(called, false); + called = true; + return 0; + } + }; + + assertEq(called, false); + regExp[Symbol.replace](""); + assertEq(called, !flag.includes("g")); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/replace-local-tolength-recompilation.js b/js/src/tests/non262/RegExp/replace-local-tolength-recompilation.js new file mode 100644 index 0000000000..e03177286f --- /dev/null +++ b/js/src/tests/non262/RegExp/replace-local-tolength-recompilation.js @@ -0,0 +1,75 @@ +// Side-effects when calling ToLength(regExp.lastIndex) in +// RegExp.prototype[@@replace] for non-global RegExp can recompile the RegExp. + +for (var flag of ["", "y"]) { + var regExp = new RegExp("a", flag); + + regExp.lastIndex = { + valueOf() { + regExp.compile("b"); + return 0; + } + }; + + var result = regExp[Symbol.replace]("b", "pass"); + assertEq(result, "pass"); +} + +// Recompilation modifies flag: +// Case 1: Adds global flag, validate by checking lastIndex. +var regExp = new RegExp("a", ""); +regExp.lastIndex = { + valueOf() { + // |regExp| is now in global mode, RegExpBuiltinExec should update the + // lastIndex property to reflect last match. + regExp.compile("a", "g"); + return 0; + } +}; +regExp[Symbol.replace]("a", ""); +assertEq(regExp.lastIndex, 1); + +// Case 2: Removes sticky flag with match, validate by checking lastIndex. +var regExp = new RegExp("a", "y"); +regExp.lastIndex = { + valueOf() { + // |regExp| is no longer sticky, RegExpBuiltinExec shouldn't modify the + // lastIndex property. + regExp.compile("a", ""); + regExp.lastIndex = 9000; + return 0; + } +}; +regExp[Symbol.replace]("a", ""); +assertEq(regExp.lastIndex, 9000); + +// Case 3.a: Removes sticky flag without match, validate by checking lastIndex. +var regExp = new RegExp("a", "y"); +regExp.lastIndex = { + valueOf() { + // |regExp| is no longer sticky, RegExpBuiltinExec shouldn't modify the + // lastIndex property. + regExp.compile("b", ""); + regExp.lastIndex = 9001; + return 0; + } +}; +regExp[Symbol.replace]("a", ""); +assertEq(regExp.lastIndex, 9001); + +// Case 3.b: Removes sticky flag without match, validate by checking lastIndex. +var regExp = new RegExp("a", "y"); +regExp.lastIndex = { + valueOf() { + // |regExp| is no longer sticky, RegExpBuiltinExec shouldn't modify the + // lastIndex property. + regExp.compile("b", ""); + regExp.lastIndex = 9002; + return 10000; + } +}; +regExp[Symbol.replace]("a", ""); +assertEq(regExp.lastIndex, 9002); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/replace-sticky-lastIndex.js b/js/src/tests/non262/RegExp/replace-sticky-lastIndex.js new file mode 100644 index 0000000000..2500b2c42d --- /dev/null +++ b/js/src/tests/non262/RegExp/replace-sticky-lastIndex.js @@ -0,0 +1,23 @@ +var BUGNUMBER = 887016; +var summary = "String.prototype.replace should do nothing if lastIndex is invalid for sticky RegExp"; + +print(BUGNUMBER + ": " + summary); + +var re = /a/y; +re.lastIndex = -1; +assertEq("a".replace(re, "b"), "b"); +re.lastIndex = 0; +assertEq("a".replace(re, "b"), "b"); +re.lastIndex = 1; +assertEq("a".replace(re, "b"), "a"); +re.lastIndex = 2; +assertEq("a".replace(re, "b"), "a"); +re.lastIndex = "foo"; +assertEq("a".replace(re, "b"), "b"); +re.lastIndex = "1"; +assertEq("a".replace(re, "b"), "a"); +re.lastIndex = {}; +assertEq("a".replace(re, "b"), "b"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/replace-sticky.js b/js/src/tests/non262/RegExp/replace-sticky.js new file mode 100644 index 0000000000..32a6e2aee0 --- /dev/null +++ b/js/src/tests/non262/RegExp/replace-sticky.js @@ -0,0 +1,21 @@ +var BUGNUMBER = 887016; +var summary = "String.prototype.replace should use and update lastIndex if sticky flag is set"; + +print(BUGNUMBER + ": " + summary); + +var input = "abcdeabcdeabcdefghij"; +var re = new RegExp("abcde", "y"); +re.test(input); +assertEq(re.lastIndex, 5); +var ret = input.replace(re, "ABCDE"); +assertEq(ret, "abcdeABCDEabcdefghij"); +assertEq(re.lastIndex, 10); +ret = input.replace(re, "ABCDE"); +assertEq(ret, "abcdeabcdeABCDEfghij"); +assertEq(re.lastIndex, 15); +ret = input.replace(re, "ABCDE"); +assertEq(ret, "abcdeabcdeabcdefghij"); +assertEq(re.lastIndex, 0); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/replace-this.js b/js/src/tests/non262/RegExp/replace-this.js new file mode 100644 index 0000000000..499304f9c0 --- /dev/null +++ b/js/src/tests/non262/RegExp/replace-this.js @@ -0,0 +1,12 @@ +var BUGNUMBER = 887016; +var summary = "RegExp.prototype[@@replace] should check |this| value."; + +print(BUGNUMBER + ": " + summary); + +for (var v of [null, 1, true, undefined, "", Symbol.iterator]) { + assertThrowsInstanceOf(() => RegExp.prototype[Symbol.replace].call(v), + TypeError); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/replace-trace.js b/js/src/tests/non262/RegExp/replace-trace.js new file mode 100644 index 0000000000..8ddf0990e0 --- /dev/null +++ b/js/src/tests/non262/RegExp/replace-trace.js @@ -0,0 +1,299 @@ +var BUGNUMBER = 887016; +var summary = "Trace RegExp.prototype[@@replace] behavior."; + +print(BUGNUMBER + ": " + summary); + +var n; +var log; +var target; +var global; +var unicode; + +var execResult; +var lastIndexResult; +var lastIndexExpected; + +var arraySetterObserved = false; +function startObserve() { + for (var i = 0; i < 10; i++) { + Object.defineProperty(Array.prototype, i, { + set: function(v) { + arraySetterObserved = true; + }, + configurable: true, + }); + } +} +function stopObserve() { + for (var i = 0; i < 10; i++) + delete Array.prototype[i] +} + +startObserve(); + +function P(A, index, matched2) { + var i = 0; + A.index = index; + return new Proxy(A, { + get(that, name) { + log += "get:result[" + name + "],"; + + // Return a different value for 2nd access to result[0]. + if (matched2 !== undefined && name == 0) { + if (i == 1) { + return matched2; + } + i++; + } + + return that[name]; + } + }); +} + +var myRegExp = { + get flags() { + log += "get:flags,"; + var flags = ""; + if (global) flags += "g"; + if (unicode) flags += "u"; + return flags; + }, + get lastIndex() { + log += "get:lastIndex,"; + return lastIndexResult[n]; + }, + set lastIndex(v) { + log += "set:lastIndex,"; + assertEq(v, lastIndexExpected[n]); + }, + get exec() { + log += "get:exec,"; + return function(S) { + log += "call:exec,"; + assertEq(S, target); + return execResult[n++]; + }; + }, +}; + +function reset() { + n = 0; + log = ""; + target = "abcAbcABC"; + global = true; + unicode = false; + arraySetterObserved = false; +} + +// Trace global with non-empty match. +reset(); +execResult = [ P(["bc"], 1), null ]; +lastIndexResult = [ , , ]; +lastIndexExpected = [ 0, , ]; +var ret = RegExp.prototype[Symbol.replace].call(myRegExp, target, "_XYZ_"); +assertEq(arraySetterObserved, false); +assertEq(ret, "a_XYZ_AbcABC"); +assertEq(log, + "get:flags," + + "set:lastIndex," + + "get:exec,call:exec," + + "get:result[0]," + + "get:exec,call:exec," + + "get:result[length],get:result[0],get:result[index],get:result[groups],"); + +// Trace global with empty match. +reset(); +execResult = [ P([""], 1), null ]; +lastIndexResult = [ , 5, ]; +lastIndexExpected = [ 0, 6, ]; +ret = RegExp.prototype[Symbol.replace].call(myRegExp, target, "_XYZ_"); +assertEq(arraySetterObserved, false); +assertEq(ret, "a_XYZ_bcAbcABC"); +assertEq(log, + "get:flags," + + "set:lastIndex," + + "get:exec,call:exec," + + "get:result[0]," + + "get:lastIndex,set:lastIndex," + + "get:exec,call:exec," + + "get:result[length],get:result[0],get:result[index],get:result[groups],"); + +// Trace global and unicode with empty match. +// 1. not surrogate pair +// 2. lead surrogate pair +// 3. trail surrogate pair +// 4. lead surrogate pair without trail surrogate pair +// 5. index overflow +reset(); +unicode = true; +// 0123 4 5678 +target = "---\uD83D\uDC38---\uD83D"; +execResult = [ P([""], 1), P([""], 2), P([""], 3), P([""], 4), P([""], 5), null ]; +lastIndexResult = [ , 2, 3, 4, 8, 9, ]; +lastIndexExpected = [ 0, 3, 5, 5, 9, 10, ]; +ret = RegExp.prototype[Symbol.replace].call(myRegExp, target, "_XYZ_"); +assertEq(arraySetterObserved, false); +assertEq(ret, "-_XYZ_-_XYZ_-_XYZ_\uD83D_XYZ_\uDC38_XYZ_---\uD83D"); +assertEq(log, + "get:flags," + + "set:lastIndex," + + "get:exec,call:exec," + + "get:result[0]," + + "get:lastIndex,set:lastIndex," + + "get:exec,call:exec," + + "get:result[0]," + + "get:lastIndex,set:lastIndex," + + "get:exec,call:exec," + + "get:result[0]," + + "get:lastIndex,set:lastIndex," + + "get:exec,call:exec," + + "get:result[0]," + + "get:lastIndex,set:lastIndex," + + "get:exec,call:exec," + + "get:result[0]," + + "get:lastIndex,set:lastIndex," + + "get:exec,call:exec," + + "get:result[length],get:result[0],get:result[index],get:result[groups]," + + "get:result[length],get:result[0],get:result[index],get:result[groups]," + + "get:result[length],get:result[0],get:result[index],get:result[groups]," + + "get:result[length],get:result[0],get:result[index],get:result[groups]," + + "get:result[length],get:result[0],get:result[index],get:result[groups],"); + +// Trace global with captures and substitutions. +reset(); +execResult = [ P(["bc", "b", "c"], 1), null ]; +lastIndexResult = [ , , ]; +lastIndexExpected = [ 0, , ]; +ret = RegExp.prototype[Symbol.replace].call(myRegExp, target, "[$&,$`,$',$1,$2,$3,$]"); +assertEq(arraySetterObserved, false); +assertEq(ret, "a[bc,a,AbcABC,b,c,$3,$]AbcABC"); +assertEq(log, + "get:flags," + + "set:lastIndex," + + "get:exec,call:exec," + + "get:result[0]," + + "get:exec,call:exec," + + "get:result[length],get:result[0],get:result[index]," + + "get:result[1],get:result[2],get:result[groups],"); + +// Trace global with empty match and captures and substitutions, +// with different matched. +reset(); +execResult = [ P(["", "b", "c"], 1, "BC"), null ]; +lastIndexResult = [ , 5, ]; +lastIndexExpected = [ 0, 6, ]; +ret = RegExp.prototype[Symbol.replace].call(myRegExp, target, "[$&,$`,$',$1,$2,$3,$]"); +assertEq(arraySetterObserved, false); +assertEq(ret, "a[BC,a,AbcABC,b,c,$3,$]AbcABC"); +assertEq(log, + "get:flags," + + "set:lastIndex," + + "get:exec,call:exec," + + "get:result[0]," + + "get:lastIndex,set:lastIndex," + + "get:exec,call:exec," + + "get:result[length],get:result[0],get:result[index]," + + "get:result[1],get:result[2],get:result[groups],"); + +// Trace global with empty match and captures and function, +// with different matched. +reset(); +execResult = [ P(["", "b", "c"], 1, "BC"), null ]; +lastIndexResult = [ , 5, ]; +lastIndexExpected = [ 0, 6, ]; +function replaceFunc(...args) { + log += "call:replaceFunc,"; + assertEq(args.length, 5); + assertEq(args[0], "BC"); + assertEq(args[1], "b"); + assertEq(args[2], "c"); + assertEq(args[3], 1); + assertEq(args[4], target); + return "_ret_"; +} +// This also tests RegExpStatics save/restore with no match. +ret = RegExp.prototype[Symbol.replace].call(myRegExp, target, replaceFunc); +assertEq(arraySetterObserved, false); +assertEq(ret, "a_ret_AbcABC"); +assertEq(log, + "get:flags," + + "set:lastIndex," + + "get:exec,call:exec," + + "get:result[0]," + + "get:lastIndex,set:lastIndex," + + "get:exec,call:exec," + + "get:result[length],get:result[0],get:result[index]," + + "get:result[1],get:result[2],get:result[groups]," + + "call:replaceFunc,"); + +// Trace global with non-empty match, move backwards. +// 2nd match shouldn't be replaced. +reset(); +execResult = [ P(["X"], 5), P(["YZ"], 1), null ]; +lastIndexResult = [ , , , ]; +lastIndexExpected = [ 0, , , ]; +ret = RegExp.prototype[Symbol.replace].call(myRegExp, target, "_XYZ_"); +assertEq(arraySetterObserved, false); +assertEq(ret, "abcAb_XYZ_ABC"); +assertEq(log, + "get:flags," + + "set:lastIndex," + + "get:exec,call:exec," + + "get:result[0]," + + "get:exec,call:exec," + + "get:result[0]," + + "get:exec,call:exec," + + "get:result[length],get:result[0],get:result[index],get:result[groups]," + + "get:result[length],get:result[0],get:result[index],get:result[groups],"); + +// Trace global with non-empty match, position + matchLength overflows. +reset(); +execResult = [ P(["fooooooo"], 7), null ]; +lastIndexResult = [ , , ]; +lastIndexExpected = [ 0, , ]; +ret = RegExp.prototype[Symbol.replace].call(myRegExp, target, "_XYZ_"); +assertEq(arraySetterObserved, false); +assertEq(ret, "abcAbcA_XYZ_"); +assertEq(log, + "get:flags," + + "set:lastIndex," + + "get:exec,call:exec," + + "get:result[0]," + + "get:exec,call:exec," + + "get:result[length],get:result[0],get:result[index],get:result[groups],"); + +// Trace global with non-empty match, position overflows. +reset(); +execResult = [ P(["fooooooo"], 12), null ]; +lastIndexResult = [ , , ]; +lastIndexExpected = [ 0, , ]; +ret = RegExp.prototype[Symbol.replace].call(myRegExp, target, "_XYZ_"); +assertEq(arraySetterObserved, false); +assertEq(ret, "abcAbcABC_XYZ_"); +assertEq(log, + "get:flags," + + "set:lastIndex," + + "get:exec,call:exec," + + "get:result[0]," + + "get:exec,call:exec," + + "get:result[length],get:result[0],get:result[index],get:result[groups],"); + +// Trace non-global. +reset(); +global = false; +execResult = [ P(["bc"], 1) ]; +lastIndexResult = [ , , ]; +lastIndexExpected = [ 0, , ]; +ret = RegExp.prototype[Symbol.replace].call(myRegExp, target, "_XYZ_"); +assertEq(arraySetterObserved, false); +assertEq(ret, "a_XYZ_AbcABC"); +assertEq(log, + "get:flags," + + "get:exec,call:exec," + + "get:result[length],get:result[0],get:result[index],get:result[groups],"); + +stopObserve(); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/replace-twoBytes.js b/js/src/tests/non262/RegExp/replace-twoBytes.js new file mode 100644 index 0000000000..660677c9f1 --- /dev/null +++ b/js/src/tests/non262/RegExp/replace-twoBytes.js @@ -0,0 +1,44 @@ +var BUGNUMBER = 1269719; +var summary = "RegExp.prototype[@@replace] should check latin1/twoBytes for all strings used in relate operation."; + +print(BUGNUMBER + ": " + summary); + +var ans = [ + "[AB$2$3$]", + "[AB$2$3$]\u3048", + "[AB$2$3$]", + "[AB$2$3$]\u3048", + "[A\u3044$2$3$]", + "[A\u3044$2$3$]\u3048", + "[A\u3044$2$3$]", + "[A\u3044$2$3$]\u3048", + "[\u3042B$2$3$]", + "[\u3042B$2$3$]\u3048", + "[\u3042B$2$3$]", + "[\u3042B$2$3$]\u3048", + "[\u3042\u3044$2$3$]", + "[\u3042\u3044$2$3$]\u3048", + "[\u3042\u3044$2$3$]", + "[\u3042\u3044$2$3$]\u3048", +]; +var i = 0; +for (var matched of ["A", "\u3042"]) { + for (var group1 of ["B", "\u3044"]) { + for (var string of ["C", "\u3046"]) { + for (var replacement of ["[$&$`$'$1$2$3$]", "[$&$`$'$1$2$3$]\u3048"]) { + var myRegExp = { + get exec() { + return function() { + return [matched, group1]; + }; + } + }; + assertEq(RegExp.prototype[Symbol.replace].call(myRegExp, string, replacement), ans[i]); + i++; + } + } + } +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/replace.js b/js/src/tests/non262/RegExp/replace.js new file mode 100644 index 0000000000..304531a5df --- /dev/null +++ b/js/src/tests/non262/RegExp/replace.js @@ -0,0 +1,34 @@ +var BUGNUMBER = 887016; +var summary = "Implement RegExp.prototype[@@replace]."; + +print(BUGNUMBER + ": " + summary); + +assertEq(RegExp.prototype[Symbol.replace].name, "[Symbol.replace]"); +assertEq(RegExp.prototype[Symbol.replace].length, 2); +var desc = Object.getOwnPropertyDescriptor(RegExp.prototype, Symbol.replace); +assertEq(desc.configurable, true); +assertEq(desc.enumerable, false); +assertEq(desc.writable, true); + +var re = /a/; +var v = re[Symbol.replace]("abcAbcABC", "X"); +assertEq(v, "XbcAbcABC"); + +re = /d/; +v = re[Symbol.replace]("abcAbcABC", "X"); +assertEq(v, "abcAbcABC"); + +re = /a/ig; +v = re[Symbol.replace]("abcAbcABC", "X"); +assertEq(v, "XbcXbcXBC"); + +re = /(a)(b)(cd)/; +v = re[Symbol.replace]("012abcd345", "_$$_$&_$`_$'_$0_$1_$2_$3_$4_$+_$"); +assertEq(v, "012_$_abcd_012_345_$0_a_b_cd_$4_$+_$345"); + +re = /(a)(b)(cd)/; +v = re[Symbol.replace]("012abcd345", "_\u3042_$$_$&_$`_$'_$0_$1_$2_$3_$4_$+_$"); +assertEq(v, "012_\u3042_$_abcd_012_345_$0_a_b_cd_$4_$+_$345"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/search-this.js b/js/src/tests/non262/RegExp/search-this.js new file mode 100644 index 0000000000..731f5480fa --- /dev/null +++ b/js/src/tests/non262/RegExp/search-this.js @@ -0,0 +1,12 @@ +var BUGNUMBER = 887016; +var summary = "RegExp.prototype[@@search] should check this value."; + +print(BUGNUMBER + ": " + summary); + +for (var v of [null, 1, true, undefined, "", Symbol.iterator]) { + assertThrowsInstanceOf(() => RegExp.prototype[Symbol.search].call(v), + TypeError); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/search-trace.js b/js/src/tests/non262/RegExp/search-trace.js new file mode 100644 index 0000000000..fc6bee754c --- /dev/null +++ b/js/src/tests/non262/RegExp/search-trace.js @@ -0,0 +1,78 @@ +var BUGNUMBER = 887016; +var summary = "Trace RegExp.prototype[@@search] behavior."; + +print(BUGNUMBER + ": " + summary); + +var n; +var log; +var target; + +var execResult; +var lastIndexResult; +var lastIndexExpected; + +function P(index) { + return new Proxy({ index }, { + get(that, name) { + log += "get:result[" + name + "],"; + return that[name]; + } + }); +} + +var myRegExp = { + get lastIndex() { + log += "get:lastIndex,"; + return lastIndexResult[n]; + }, + set lastIndex(v) { + log += "set:lastIndex,"; + assertEq(v, lastIndexExpected[n]); + }, + get exec() { + log += "get:exec,"; + return function(S) { + log += "call:exec,"; + assertEq(S, target); + return execResult[n++]; + }; + }, +}; + +function reset() { + n = 0; + log = ""; + target = "abcAbcABC"; +} + +// Trace hit. +reset(); +execResult = [ P(16) ]; +lastIndexResult = [ 10, , ]; +lastIndexExpected = [ 0, 10 ]; +var ret = RegExp.prototype[Symbol.search].call(myRegExp, target); +assertEq(ret, 16); +assertEq(log, + "get:lastIndex," + + "set:lastIndex," + + "get:exec,call:exec," + + "get:lastIndex," + + "set:lastIndex," + + "get:result[index],"); + +// Trace not hit. +reset(); +execResult = [ null ]; +lastIndexResult = [ 10, , ]; +lastIndexExpected = [ 0, 10 ]; +ret = RegExp.prototype[Symbol.search].call(myRegExp, target); +assertEq(ret, -1); +assertEq(log, + "get:lastIndex," + + "set:lastIndex," + + "get:exec,call:exec," + + "get:lastIndex," + + "set:lastIndex,"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/search.js b/js/src/tests/non262/RegExp/search.js new file mode 100644 index 0000000000..0875ee47ed --- /dev/null +++ b/js/src/tests/non262/RegExp/search.js @@ -0,0 +1,26 @@ +var BUGNUMBER = 887016; +var summary = "Implement RegExp.prototype[@@search]."; + +print(BUGNUMBER + ": " + summary); + +assertEq(RegExp.prototype[Symbol.search].name, "[Symbol.search]"); +assertEq(RegExp.prototype[Symbol.search].length, 1); +var desc = Object.getOwnPropertyDescriptor(RegExp.prototype, Symbol.search); +assertEq(desc.configurable, true); +assertEq(desc.enumerable, false); +assertEq(desc.writable, true); + +var re = /B/; +var v = re[Symbol.search]("abcAbcABC"); +assertEq(v, 7); + +re = /B/i; +v = re[Symbol.search]("abcAbcABCD"); +assertEq(v, 1); + +re = /d/; +v = re[Symbol.search]("abcAbcABCD"); +assertEq(v, -1); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/shell.js b/js/src/tests/non262/RegExp/shell.js new file mode 100644 index 0000000000..8d52ad35df --- /dev/null +++ b/js/src/tests/non262/RegExp/shell.js @@ -0,0 +1,256 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Date: 07 February 2001 + * + * Functionality common to RegExp testing - + */ +//----------------------------------------------------------------------------- + +(function(global) { + + var MSG_PATTERN = '\nregexp = '; + var MSG_STRING = '\nstring = '; + var MSG_EXPECT = '\nExpect: '; + var MSG_ACTUAL = '\nActual: '; + var ERR_LENGTH = '\nERROR !!! match arrays have different lengths:'; + var ERR_MATCH = '\nERROR !!! regexp failed to give expected match array:'; + var ERR_NO_MATCH = '\nERROR !!! regexp FAILED to match anything !!!'; + var ERR_UNEXP_MATCH = '\nERROR !!! regexp MATCHED when we expected it to fail !!!'; + var CHAR_LBRACKET = '['; + var CHAR_RBRACKET = ']'; + var CHAR_QT_DBL = '"'; + var CHAR_QT = "'"; + var CHAR_NL = '\n'; + var CHAR_COMMA = ','; + var CHAR_SPACE = ' '; + var TYPE_STRING = typeof 'abc'; + + + + global.testRegExp = function testRegExp(statuses, patterns, strings, actualmatches, expectedmatches) + { + var status = ''; + var pattern = new RegExp(); + var string = ''; + var actualmatch = new Array(); + var expectedmatch = new Array(); + var state = ''; + var lActual = -1; + var lExpect = -1; + + + for (var i=0; i != patterns.length; i++) + { + status = statuses[i]; + pattern = patterns[i]; + string = strings[i]; + actualmatch=actualmatches[i]; + expectedmatch=expectedmatches[i]; + state = getState(status, pattern, string); + + description = status; + + if(actualmatch) + { + actual = formatArray(actualmatch); + if(expectedmatch) + { + // expectedmatch and actualmatch are arrays - + lExpect = expectedmatch.length; + lActual = actualmatch.length; + + var expected = formatArray(expectedmatch); + + if (lActual != lExpect) + { + reportCompare(lExpect, lActual, + state + ERR_LENGTH + + MSG_EXPECT + expected + + MSG_ACTUAL + actual + + CHAR_NL + ); + continue; + } + + // OK, the arrays have same length - + if (expected != actual) + { + reportCompare(expected, actual, + state + ERR_MATCH + + MSG_EXPECT + expected + + MSG_ACTUAL + actual + + CHAR_NL + ); + } + else + { + reportCompare(expected, actual, state) + } + + } + else //expectedmatch is null - that is, we did not expect a match - + { + expected = expectedmatch; + reportCompare(expected, actual, + state + ERR_UNEXP_MATCH + + MSG_EXPECT + expectedmatch + + MSG_ACTUAL + actual + + CHAR_NL + ); + } + + } + else // actualmatch is null + { + if (expectedmatch) + { + actual = actualmatch; + reportCompare(expected, actual, + state + ERR_NO_MATCH + + MSG_EXPECT + expectedmatch + + MSG_ACTUAL + actualmatch + + CHAR_NL + ); + } + else // we did not expect a match + { + // Being ultra-cautious. Presumably expectedmatch===actualmatch===null + expected = expectedmatch; + actual = actualmatch; + reportCompare (expectedmatch, actualmatch, state); + } + } + } + } + + function getState(status, pattern, string) + { + /* + * Escape \n's, etc. to make them LITERAL in the presentation string. + * We don't have to worry about this in |pattern|; such escaping is + * done automatically by pattern.toString(), invoked implicitly below. + * + * One would like to simply do: string = string.replace(/(\s)/g, '\$1'). + * However, the backreference $1 is not a literal string value, + * so this method doesn't work. + * + * Also tried string = string.replace(/(\s)/g, escape('$1')); + * but this just inserts the escape of the literal '$1', i.e. '%241'. + */ + string = string.replace(/\n/g, '\\n'); + string = string.replace(/\r/g, '\\r'); + string = string.replace(/\t/g, '\\t'); + string = string.replace(/\v/g, '\\v'); + string = string.replace(/\f/g, '\\f'); + + return (status + MSG_PATTERN + pattern + MSG_STRING + singleQuote(string)); + } + + + + /* + * If available, arr.toSource() gives more detail than arr.toString() + * + * var arr = Array(1,2,'3'); + * + * arr.toSource() + * [1, 2, "3"] + * + * arr.toString() + * 1,2,3 + * + * But toSource() doesn't exist in Rhino, so use our own imitation, below - + * + */ + function formatArray(arr) + { + try + { + return arr.toSource(); + } + catch(e) + { + return toSource(arr); + } + } + + + /* + * Imitate SpiderMonkey's arr.toSource() method: + * + * a) Double-quote each array element that is of string type + * b) Represent |undefined| and |null| by empty strings + * c) Delimit elements by a comma + single space + * d) Do not add delimiter at the end UNLESS the last element is |undefined| + * e) Add square brackets to the beginning and end of the string + */ + function toSource(arr) + { + var delim = CHAR_COMMA + CHAR_SPACE; + var elt = ''; + var ret = ''; + var len = arr.length; + + for (i=0; i genericSource(), TypeError); +assertThrowsInstanceOf(() => genericSource(1), TypeError); +assertThrowsInstanceOf(() => genericSource(""), TypeError); +assertThrowsInstanceOf(() => genericSource({}), TypeError); +assertThrowsInstanceOf(() => genericSource(new Proxy(/foo/, {get(){ return true; }})), TypeError); + +function genericSource(obj) { + return Object.getOwnPropertyDescriptor(RegExp.prototype, "source").get.call(obj); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/split-deleted-flags.js b/js/src/tests/non262/RegExp/split-deleted-flags.js new file mode 100644 index 0000000000..d2ccc852d1 --- /dev/null +++ b/js/src/tests/non262/RegExp/split-deleted-flags.js @@ -0,0 +1,11 @@ +var BUGNUMBER = 1322319; +var summary = "RegExp.prototype.split should throw if RegRxp.prototype.flags is deleted." + +print(BUGNUMBER + ": " + summary); + +delete RegExp.prototype.flags; + +assertThrowsInstanceOf(() => "aaaaa".split(/a/), SyntaxError); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/split-flags-on-obj.js b/js/src/tests/non262/RegExp/split-flags-on-obj.js new file mode 100644 index 0000000000..8c68efed57 --- /dev/null +++ b/js/src/tests/non262/RegExp/split-flags-on-obj.js @@ -0,0 +1,21 @@ +var BUGNUMBER = 0; +var summary = "RegExp.prototype.split should reflect the change to Object.prototype.flags."; + +print(BUGNUMBER + ": " + summary); + +Object.defineProperty(Object.prototype, "flags", Object.getOwnPropertyDescriptor(RegExp.prototype, "flags")); +delete RegExp.prototype.flags; + +let re = /a/i; +let a = re[Symbol.split]("1a2A3a4A5"); +assertDeepEq(a, ["1", "2", "3", "4", "5"]); + +delete Object.prototype.flags; + +Object.prototype.flags = ""; + +a = re[Symbol.split]("1a2A3a4A5"); +assertDeepEq(a, ["1", "2A3", "4A5"]); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/split-invalid-lastIndex.js b/js/src/tests/non262/RegExp/split-invalid-lastIndex.js new file mode 100644 index 0000000000..3def559ad0 --- /dev/null +++ b/js/src/tests/non262/RegExp/split-invalid-lastIndex.js @@ -0,0 +1,31 @@ +var BUGNUMBER = 1263851; +var summary = "RegExp.prototype[@@split] should handle if lastIndex is out of bound."; + +print(BUGNUMBER + ": " + summary); + +var myRegExp = { + get constructor() { + return { + get [Symbol.species]() { + return function() { + return { + get lastIndex() { + return 9; + }, + set lastIndex(v) {}, + exec() { + return []; + } + }; + }; + } + }; + } +}; +var result = RegExp.prototype[Symbol.split].call(myRegExp, "abcde");; +assertEq(result.length, 2); +assertEq(result[0], ""); +assertEq(result[1], ""); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/split-limit.js b/js/src/tests/non262/RegExp/split-limit.js new file mode 100644 index 0000000000..5fa194b90b --- /dev/null +++ b/js/src/tests/non262/RegExp/split-limit.js @@ -0,0 +1,14 @@ +var BUGNUMBER = 1287525; +var summary = "RegExp.prototype[@@split] shouldn't use optimized path if limit is not number."; + +print(BUGNUMBER + ": " + summary); + +var rx = /a/; +var r = rx[Symbol.split]("abba", {valueOf() { + RegExp.prototype.exec = () => null; + return 100; +}}); +assertEq(r.length, 1); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/split-obj.js b/js/src/tests/non262/RegExp/split-obj.js new file mode 100644 index 0000000000..75c09f38d1 --- /dev/null +++ b/js/src/tests/non262/RegExp/split-obj.js @@ -0,0 +1,12 @@ +var BUGNUMBER = 887016; +var summary = "RegExp.prototype[@@split] should check if this value is RegExp."; + +print(BUGNUMBER + ": " + summary); + +var obj = { flags: "", toString: () => "-" }; +assertDeepEq(RegExp.prototype[Symbol.split].call(obj, "a-b-c"), + ["a", "b", "c"]); + +if (typeof reportCompare === "function") + reportCompare(true, true); + diff --git a/js/src/tests/non262/RegExp/split-prop-access.js b/js/src/tests/non262/RegExp/split-prop-access.js new file mode 100644 index 0000000000..73c5bebb31 --- /dev/null +++ b/js/src/tests/non262/RegExp/split-prop-access.js @@ -0,0 +1,19 @@ +var BUGNUMBER = 1287525; +var summary = 'String.prototype.split should call ToUint32(limit) before ToString(separator).'; + +print(BUGNUMBER + ": " + summary); + +var accessed = false; + +var rx = /a/; +Object.defineProperty(rx, Symbol.match, { + get() { + accessed = true; + } +}); +rx[Symbol.split]("abba"); + +assertEq(accessed, true); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/split-this.js b/js/src/tests/non262/RegExp/split-this.js new file mode 100644 index 0000000000..ece29fe8a2 --- /dev/null +++ b/js/src/tests/non262/RegExp/split-this.js @@ -0,0 +1,12 @@ +var BUGNUMBER = 887016; +var summary = "RegExp.prototype[@@split] should check this value."; + +print(BUGNUMBER + ": " + summary); + +for (var v of [null, 1, true, undefined, "", Symbol.iterator]) { + assertThrowsInstanceOf(() => RegExp.prototype[Symbol.split].call(v), + TypeError); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/split-trace.js b/js/src/tests/non262/RegExp/split-trace.js new file mode 100644 index 0000000000..fe7fe95981 --- /dev/null +++ b/js/src/tests/non262/RegExp/split-trace.js @@ -0,0 +1,229 @@ +var BUGNUMBER = 887016; +var summary = "Trace RegExp.prototype[@@split] behavior."; + +print(BUGNUMBER + ": " + summary); + +var n; +var log; +var target; +var flags; +var expectedFlags; + +var execResult; +var lastIndexResult; +var lastIndexExpected; + +var arraySetterObserved = false; +function startObserve() { + for (var i = 0; i < 10; i++) { + Object.defineProperty(Array.prototype, i, { + set: function(v) { + arraySetterObserved = true; + }, + configurable: true, + }); + } +} +function stopObserve() { + for (var i = 0; i < 10; i++) + delete Array.prototype[i] +} + +startObserve(); + +function P(A) { + return new Proxy(A, { + get(that, name) { + log += "get:result[" + name + "],"; + return that[name]; + } + }); +} + +var myRegExp = { + get constructor() { + log += "get:constructor,"; + return { + get [Symbol.species]() { + log += "get:species,"; + return function(pattern, flags) { + assertEq(pattern, myRegExp); + assertEq(flags, expectedFlags); + log += "call:constructor,"; + return { + get lastIndex() { + log += "get:lastIndex,"; + return lastIndexResult[n]; + }, + set lastIndex(v) { + log += "set:lastIndex,"; + assertEq(v, lastIndexExpected[n]); + }, + get flags() { + log += "get:flags,"; + return flags; + }, + get exec() { + log += "get:exec,"; + return function(S) { + log += "call:exec,"; + assertEq(S, target); + return execResult[n++]; + }; + }, + }; + }; + } + }; + }, + get flags() { + log += "get:flags,"; + return flags; + }, +}; + +function reset() { + n = 0; + log = ""; + target = "abcde"; + flags = ""; + expectedFlags = "y"; + arraySetterObserved = false; +} + +// Trace match and no match. +reset(); +execResult = [ null, P(["b"]), null, P(["d"]), null ]; +lastIndexResult = [ , , 2, , 4, , ]; +lastIndexExpected = [ 0, 1, 2, 3, 4, ]; +var ret = RegExp.prototype[Symbol.split].call(myRegExp, target); +assertEq(arraySetterObserved, false); +assertEq(JSON.stringify(ret), `["a","c","e"]`); +assertEq(log, + "get:constructor," + + "get:species," + + "get:flags," + + "call:constructor," + + "set:lastIndex,get:exec,call:exec," + + "set:lastIndex,get:exec,call:exec,get:lastIndex," + + "get:result[length]," + + "set:lastIndex,get:exec,call:exec," + + "set:lastIndex,get:exec,call:exec,get:lastIndex," + + "get:result[length]," + + "set:lastIndex,get:exec,call:exec,"); + +// Trace non-empty flags, empty target, no match. +reset(); +flags = "iy"; +expectedFlags = "iy"; +target = ""; +execResult = [ null ]; +lastIndexResult = []; +lastIndexExpected = []; +ret = RegExp.prototype[Symbol.split].call(myRegExp, target); +assertEq(arraySetterObserved, false); +assertEq(JSON.stringify(ret), `[""]`); +assertEq(log, + "get:constructor," + + "get:species," + + "get:flags," + + "call:constructor," + + "get:exec,call:exec,"); + +// Trace empty target, match. +reset(); +target = ""; +execResult = [ P([""]) ]; +lastIndexResult = []; +lastIndexExpected = []; +ret = RegExp.prototype[Symbol.split].call(myRegExp, target); +assertEq(arraySetterObserved, false); +assertEq(JSON.stringify(ret), `[]`); +assertEq(log, + "get:constructor," + + "get:species," + + "get:flags," + + "call:constructor," + + "get:exec,call:exec,"); + +// Trace captures. +reset(); +target = "abc"; +execResult = [ null, P(["b", "X", "YZ"]), null ]; +lastIndexResult = [ , , 2, , ]; +lastIndexExpected = [ 0, 1, 2, ]; +ret = RegExp.prototype[Symbol.split].call(myRegExp, target); +assertEq(arraySetterObserved, false); +assertEq(JSON.stringify(ret), `["a","X","YZ","c"]`); +assertEq(log, + "get:constructor," + + "get:species," + + "get:flags," + + "call:constructor," + + "set:lastIndex,get:exec,call:exec," + + "set:lastIndex,get:exec,call:exec,get:lastIndex," + + "get:result[length]," + + "get:result[1],get:result[2]," + + "set:lastIndex,get:exec,call:exec,"); + +// Trace unicode. +// 1. not surrogate pair +// 2. lead surrogate pair +// 3. trail surrogate pair +// 4. lead surrogate pair without trail surrogate pair +// 5. index overflow +reset(); +flags = "u"; +expectedFlags = "uy"; +target = "-\uD83D\uDC38\uDC38\uD83D"; +execResult = [ null, null, null, null ]; +lastIndexResult = [ , , , , , ]; +lastIndexExpected = [ 0, 1, 3, 4, ]; +ret = RegExp.prototype[Symbol.split].call(myRegExp, target); +assertEq(arraySetterObserved, false); +assertEq(JSON.stringify(ret), `["-\uD83D\uDC38\\udc38\\ud83d"]`); +assertEq(log, + "get:constructor," + + "get:species," + + "get:flags," + + "call:constructor," + + "set:lastIndex,get:exec,call:exec," + + "set:lastIndex,get:exec,call:exec," + + "set:lastIndex,get:exec,call:exec," + + "set:lastIndex,get:exec,call:exec,"); + +// Trace unicode, match, same position and different position. +reset(); +flags = "u"; +expectedFlags = "uy"; +target = "-\uD83D\uDC38\uDC38\uD83D"; +var E = P(["", "X"]); +execResult = [ E, E, E, E, E, E, E ]; +lastIndexResult = [ , 0, 1, 1, 3, 3, 4, 4 ]; +lastIndexExpected = [ 0, 1, 1, 3, 3, 4, 4, ]; +ret = RegExp.prototype[Symbol.split].call(myRegExp, target); +assertEq(arraySetterObserved, false); +assertEq(JSON.stringify(ret), `["-","X","\uD83D\uDC38","X","\\udc38","X","\\ud83d"]`); +assertEq(log, + "get:constructor," + + "get:species," + + "get:flags," + + "call:constructor," + + "set:lastIndex,get:exec,call:exec,get:lastIndex," + + "set:lastIndex,get:exec,call:exec,get:lastIndex," + + "get:result[length]," + + "get:result[1]," + + "set:lastIndex,get:exec,call:exec,get:lastIndex," + + "set:lastIndex,get:exec,call:exec,get:lastIndex," + + "get:result[length]," + + "get:result[1]," + + "set:lastIndex,get:exec,call:exec,get:lastIndex," + + "set:lastIndex,get:exec,call:exec,get:lastIndex," + + "get:result[length]," + + "get:result[1]," + + "set:lastIndex,get:exec,call:exec,get:lastIndex,"); + +stopObserve(); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/split.js b/js/src/tests/non262/RegExp/split.js new file mode 100644 index 0000000000..d7e28d7919 --- /dev/null +++ b/js/src/tests/non262/RegExp/split.js @@ -0,0 +1,30 @@ +var BUGNUMBER = 887016; +var summary = "Implement RegExp.prototype[@@split]."; + +print(BUGNUMBER + ": " + summary); + +assertEq(RegExp.prototype[Symbol.split].name, "[Symbol.split]"); +assertEq(RegExp.prototype[Symbol.split].length, 2); +var desc = Object.getOwnPropertyDescriptor(RegExp.prototype, Symbol.split); +assertEq(desc.configurable, true); +assertEq(desc.enumerable, false); +assertEq(desc.writable, true); + +var re = /b/; +var v = re[Symbol.split]("abcAbcABC"); +assertEq(JSON.stringify(v), `["a","cA","cABC"]`); + +re = /d/; +v = re[Symbol.split]("abcAbcABC"); +assertEq(JSON.stringify(v), `["abcAbcABC"]`); + +re = /b/ig; +v = re[Symbol.split]("abcAbcABC"); +assertEq(JSON.stringify(v), `["a","cA","cA","C"]`); + +re = /b/ig; +v = re[Symbol.split]("abcAbcABC", 2); +assertEq(JSON.stringify(v), `["a","cA"]`); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/sticky.js b/js/src/tests/non262/RegExp/sticky.js new file mode 100644 index 0000000000..13a6debe95 --- /dev/null +++ b/js/src/tests/non262/RegExp/sticky.js @@ -0,0 +1,126 @@ +var BUGNUMBER = 773687; +var summary = 'sticky flag should not break assertion behavior.'; + +print(BUGNUMBER + ": " + summary); + +function test(re, text, expectations) { + // Sanity check for test data itself. + assertEq(expectations.length, text.length + 1); + + for (var i = 0; i < expectations.length; i++) { + var result = expectations[i]; + + re.lastIndex = i; + var match = re.exec(text); + if (result === null) { + assertEq(re.lastIndex, 0); + assertEq(match, null); + } else { + assertEq(re.lastIndex, result.lastIndex); + assertEq(match !== null, true); + assertEq(match.length, result.matches.length); + for (var j = 0; j < result.matches.length; j++) + assertEq(match[j], result.matches[j]); + assertEq(match.index, result.index); + } + } +} + +// simple text +test(/bc/y, "abcabd", [ + null, + { lastIndex: 3, matches: ["bc"], index: 1 }, + null, + null, + null, + null, + null, +]); + +// complex pattern +test(/bc|c|d/y, "abcabd", [ + null, + { lastIndex: 3, matches: ["bc"], index: 1 }, + { lastIndex: 3, matches: ["c"], index: 2 }, + null, + null, + { lastIndex: 6, matches: ["d"], index: 5 }, + null, +]); + +test(/.*(bc|c|d)/y, "abcabd", [ + { lastIndex: 6, matches: ["abcabd", "d"], index: 0 }, + { lastIndex: 6, matches: ["bcabd", "d"], index: 1 }, + { lastIndex: 6, matches: ["cabd", "d"], index: 2 }, + { lastIndex: 6, matches: ["abd", "d"], index: 3 }, + { lastIndex: 6, matches: ["bd", "d"], index: 4 }, + { lastIndex: 6, matches: ["d", "d"], index: 5 }, + null, +]); + +test(/.*?(bc|c|d)/y, "abcabd", [ + { lastIndex: 3, matches: ["abc", "bc"], index: 0 }, + { lastIndex: 3, matches: ["bc", "bc"], index: 1 }, + { lastIndex: 3, matches: ["c", "c"], index: 2 }, + { lastIndex: 6, matches: ["abd", "d"], index: 3 }, + { lastIndex: 6, matches: ["bd", "d"], index: 4 }, + { lastIndex: 6, matches: ["d", "d"], index: 5 }, + null, +]); + +test(/(bc|.*c|d)/y, "abcabd", [ + { lastIndex: 3, matches: ["abc", "abc"], index: 0 }, + { lastIndex: 3, matches: ["bc", "bc"], index: 1 }, + { lastIndex: 3, matches: ["c", "c"], index: 2 }, + null, + null, + { lastIndex: 6, matches: ["d", "d"], index: 5 }, + null, +]); + +// ^ assertions +test(/^/y, "abcabc", [ + { lastIndex: 0, matches: [""], index: 0 }, + null, + null, + null, + null, + null, + null, +]); + +test(/^a/my, "abc\nabc", [ + { lastIndex: 1, matches: ["a"], index: 0 }, + null, + null, + null, + { lastIndex: 5, matches: ["a"], index: 4 }, + null, + null, + null, +]); + +// \b assertions +test(/\b/y, "abc bc", [ + { lastIndex: 0, matches: [""], index: 0 }, + null, + null, + { lastIndex: 3, matches: [""], index: 3 }, + { lastIndex: 4, matches: [""], index: 4 }, + null, + { lastIndex: 6, matches: [""], index: 6 }, +]); + +// \B assertions +test(/\B/y, "abc bc", [ + null, + { lastIndex: 1, matches: [""], index: 1 }, + { lastIndex: 2, matches: [""], index: 2 }, + null, + null, + { lastIndex: 5, matches: [""], index: 5 }, + null, +]); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/test-emptyMatch.js b/js/src/tests/non262/RegExp/test-emptyMatch.js new file mode 100644 index 0000000000..6103c28d52 --- /dev/null +++ b/js/src/tests/non262/RegExp/test-emptyMatch.js @@ -0,0 +1,23 @@ +var BUGNUMBER = 1322035; +var summary = 'RegExp.prototype.test should update lastIndex to correct position even if pattern starts with .*'; + +print(BUGNUMBER + ": " + summary); + +var regExp = /.*x?/g; +regExp.test('12345'); +assertEq(regExp.lastIndex, 5); + +regExp = /.*x*/g; +regExp.test('12345'); +assertEq(regExp.lastIndex, 5); + +regExp = /.*()/g; +regExp.test('12345'); +assertEq(regExp.lastIndex, 5); + +regExp = /.*(x|)/g; +regExp.test('12345'); +assertEq(regExp.lastIndex, 5); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/test-trailing.js b/js/src/tests/non262/RegExp/test-trailing.js new file mode 100644 index 0000000000..7cb910ee62 --- /dev/null +++ b/js/src/tests/non262/RegExp/test-trailing.js @@ -0,0 +1,31 @@ +var BUGNUMBER = 1304737; +var summary = "Trailing .* should not be ignored on matchOnly match."; + +print(BUGNUMBER + ": " + summary); + +function test(r, lastIndexIsZero) { + r.lastIndex = 0; + r.test("foo"); + assertEq(r.lastIndex, lastIndexIsZero ? 0 : 3); + + r.lastIndex = 0; + r.test("foo\nbar"); + assertEq(r.lastIndex, lastIndexIsZero ? 0 : 3); + + var input = "foo" + ".bar".repeat(20000); + r.lastIndex = 0; + r.test(input); + assertEq(r.lastIndex, lastIndexIsZero ? 0 : input.length); + + r.lastIndex = 0; + r.test(input + "\nbaz"); + assertEq(r.lastIndex, lastIndexIsZero ? 0 : input.length); +} + +test(/f.*/, true); +test(/f.*/g, false); +test(/f.*/y, false); +test(/f.*/gy, false); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/toString.js b/js/src/tests/non262/RegExp/toString.js new file mode 100644 index 0000000000..5ffbeed331 --- /dev/null +++ b/js/src/tests/non262/RegExp/toString.js @@ -0,0 +1,42 @@ +var BUGNUMBER = 1079919; +var summary = "Make RegExp.prototype.toString to be a generic function."; + +print(BUGNUMBER + ": " + summary); + +assertEq(RegExp.prototype.toString(), "/(?:)/"); +assertEq(/foo/.toString(), "/foo/"); +assertEq(/foo/i.toString(), "/foo/i"); +assertEq(/foo/gimy.toString(), "/foo/gimy"); +assertEq(/foo/igym.toString(), "/foo/gimy"); +assertEq(/\n\r/.toString(), "/\\n\\r/"); +assertEq(/\u2028\u2029/.toString(), "/\\u2028\\u2029/"); +assertEq(/\//.toString(), "/\\//"); +assertEq(RegExp().toString(), "/(?:)/"); +assertEq(RegExp("", "gimy").toString(), "/(?:)/gimy"); +assertEq(RegExp("\n\r").toString(), "/\\n\\r/"); +assertEq(RegExp("\u2028\u2029").toString(), "/\\u2028\\u2029/"); +assertEq(RegExp("/").toString(), "/\\//"); + +assertThrowsInstanceOf(() => RegExp.prototype.toString.call(), TypeError); +assertThrowsInstanceOf(() => RegExp.prototype.toString.call(1), TypeError); +assertThrowsInstanceOf(() => RegExp.prototype.toString.call(""), TypeError); +assertEq(RegExp.prototype.toString.call({}), "/undefined/undefined"); +assertEq(RegExp.prototype.toString.call({ source:"foo", flags:"bar" }), "/foo/bar"); + +var a = []; +var p = new Proxy({}, { + get(that, name) { + a.push(name); + return { + toString() { + a.push(name + "-tostring"); + return name; + } + }; + } +}); +assertEq(RegExp.prototype.toString.call(p), "/source/flags"); +assertEq(a.join(","), "source,source-tostring,flags,flags-tostring"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/unicode-back-reference.js b/js/src/tests/non262/RegExp/unicode-back-reference.js new file mode 100644 index 0000000000..2a65432a1d --- /dev/null +++ b/js/src/tests/non262/RegExp/unicode-back-reference.js @@ -0,0 +1,39 @@ +var BUGNUMBER = 1135377; +var summary = "Implement RegExp unicode flag -- back reference should not match lead surrogate that has corresponding trail surrogate."; + +print(BUGNUMBER + ": " + summary); + +// The last character of back reference is not a surrogate. +assertEqArray(/foo(.+)bar\1/u.exec("fooAbarA\uDC00"), + ["fooAbarA", "A"]); +assertEqArray(/foo(.+)bar\1/u.exec("fooAbarA\uD834"), + ["fooAbarA", "A"]); +assertEqArray(/foo(.+)bar\1/u.exec("fooAbarAA"), + ["fooAbarA", "A"]); +assertEqArray(/foo(.+)bar\1/u.exec("fooAbarA"), + ["fooAbarA", "A"]); + +// The last character of back reference is a lead surrogate. +assertEq(/foo(.+)bar\1/u.exec("foo\uD834bar\uD834\uDC00"), null); +assertEqArray(/foo(.+)bar\1/u.exec("foo\uD834bar\uD834\uD834"), + ["foo\uD834bar\uD834", "\uD834"]); +assertEqArray(/foo(.+)bar\1/u.exec("foo\uD834bar\uD834A"), + ["foo\uD834bar\uD834", "\uD834"]); +assertEqArray(/foo(.+)bar\1/u.exec("foo\uD834bar\uD834"), + ["foo\uD834bar\uD834", "\uD834"]); + +// The last character of back reference is a trail surrogate. +assertEqArray(/foo(.+)bar\1/u.exec("foo\uDC00bar\uDC00\uDC00"), + ["foo\uDC00bar\uDC00", "\uDC00"]); +assertEqArray(/foo(.+)bar\1/u.exec("foo\uDC00bar\uDC00\uD834"), + ["foo\uDC00bar\uDC00", "\uDC00"]); +assertEqArray(/foo(.+)bar\1/u.exec("foo\uDC00bar\uDC00A"), + ["foo\uDC00bar\uDC00", "\uDC00"]); +assertEqArray(/foo(.+)bar\1/u.exec("foo\uDC00bar\uDC00"), + ["foo\uDC00bar\uDC00", "\uDC00"]); + +// Pattern should not match to surrogate pair partially. +assertEq(/^(.+)\1$/u.exec("\uDC00foobar\uD834\uDC00foobar\uD834"), null); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/unicode-braced.js b/js/src/tests/non262/RegExp/unicode-braced.js new file mode 100644 index 0000000000..97df7acabf --- /dev/null +++ b/js/src/tests/non262/RegExp/unicode-braced.js @@ -0,0 +1,166 @@ +var BUGNUMBER = 1135377; +var summary = "Implement RegExp unicode flag -- braced pattern in RegExpUnicodeEscapeSequence."; + +print(BUGNUMBER + ": " + summary); + +// ==== standalone ==== + +assertEqArray(/\u{41}/u.exec("ABC"), + ["A"]); +assertEqArray(/\u{41}/.exec("ABC" + "u".repeat(41)), + ["u".repeat(41)]); + +assertEqArray(/\u{4A}/u.exec("JKL"), + ["J"]); +assertEqArray(/\u{4A}/.exec("JKLu{4A}"), + ["u{4A}"]); + +assertEqArray(/\u{1F438}/u.exec("\u{1F438}"), + ["\u{1F438}"]); +assertEqArray(/\u{1F438}/.exec("u{1F438}"), + ["u{1F438}"]); + +assertEqArray(/\u{0}/u.exec("\u{0}"), + ["\u{0}"]); +assertEqArray(/\u{10FFFF}/u.exec("\u{10FFFF}"), + ["\u{10FFFF}"]); +assertEqArray(/\u{10ffff}/u.exec("\u{10FFFF}"), + ["\u{10FFFF}"]); + +// leading 0 +assertEqArray(/\u{0000000000000000000000}/u.exec("\u{0}"), + ["\u{0}"]); +assertEqArray(/\u{000000000000000010FFFF}/u.exec("\u{10FFFF}"), + ["\u{10FFFF}"]); + +// RegExp constructor +assertEqArray(new RegExp("\\u{0}", "u").exec("\u{0}"), + ["\u{0}"]); +assertEqArray(new RegExp("\\u{41}", "u").exec("ABC"), + ["A"]); +assertEqArray(new RegExp("\\u{1F438}", "u").exec("\u{1F438}"), + ["\u{1F438}"]); +assertEqArray(new RegExp("\\u{10FFFF}", "u").exec("\u{10FFFF}"), + ["\u{10FFFF}"]); + +assertEqArray(new RegExp("\\u{0000000000000000}", "u").exec("\u{0}"), + ["\u{0}"]); + +assertEqArray(eval(`/\\u{${"0".repeat(Math.pow(2, 24)) + "1234"}}/u`).exec("\u{1234}"), + ["\u{1234}"]); +assertEqArray(new RegExp(`\\u{${"0".repeat(Math.pow(2, 24)) + "1234"}}`, "u").exec("\u{1234}"), + ["\u{1234}"]); + +// ==== ? ==== + +assertEqArray(/\u{1F438}?/u.exec("\u{1F438}"), + ["\u{1F438}"]); +assertEqArray(/\u{1F438}?/u.exec(""), + [""]); + +// lead-only target +assertEqArray(/\u{1F438}?/u.exec("\uD83D"), + [""]); + +// RegExp constructor +assertEqArray(new RegExp("\\u{1F438}?", "u").exec("\u{1F438}"), + ["\u{1F438}"]); +assertEqArray(new RegExp("\\u{1F438}?", "u").exec(""), + [""]); +assertEqArray(new RegExp("\\u{1F438}?", "u").exec("\uD83D"), + [""]); + +// ==== + ==== + +assertEqArray(/\u{1F438}+/u.exec("\u{1F438}"), + ["\u{1F438}"]); +assertEqArray(/\u{1F438}+/u.exec("\u{1F438}\u{1F438}"), + ["\u{1F438}\u{1F438}"]); +assertEq(/\u{1F438}+/u.exec(""), + null); + +// lead-only target +assertEq(/\u{1F438}+/u.exec("\uD83D"), + null); +assertEqArray(/\u{1F438}+/u.exec("\uD83D\uDC38\uDC38"), + ["\uD83D\uDC38"]); + +// ==== * ==== + +assertEqArray(/\u{1F438}*/u.exec("\u{1F438}"), + ["\u{1F438}"]); +assertEqArray(/\u{1F438}*/u.exec("\u{1F438}\u{1F438}"), + ["\u{1F438}\u{1F438}"]); +assertEqArray(/\u{1F438}*/u.exec(""), + [""]); + +// lead-only target +assertEqArray(/\u{1F438}*/u.exec("\uD83D"), + [""]); +assertEqArray(/\u{1F438}*/u.exec("\uD83D\uDC38\uDC38"), + ["\uD83D\uDC38"]); + +// ==== lead-only ==== + +// match only non-surrogate pair +assertEqArray(/\u{D83D}/u.exec("\uD83D\uDBFF"), + ["\uD83D"]); +assertEq(/\u{D83D}/u.exec("\uD83D\uDC00"), + null); +assertEq(/\u{D83D}/u.exec("\uD83D\uDFFF"), + null); +assertEqArray(/\u{D83D}/u.exec("\uD83D\uE000"), + ["\uD83D"]); + +// match before non-tail char +assertEqArray(/\u{D83D}/u.exec("\uD83D"), + ["\uD83D"]); +assertEqArray(/\u{D83D}/u.exec("\uD83DA"), + ["\uD83D"]); + +// ==== trail-only ==== + +// match only non-surrogate pair +assertEqArray(/\u{DC38}/u.exec("\uD7FF\uDC38"), + ["\uDC38"]); +assertEq(/\u{DC38}/u.exec("\uD800\uDC38"), + null); +assertEq(/\u{DC38}/u.exec("\uDBFF\uDC38"), + null); +assertEqArray(/\u{DC38}/u.exec("\uDC00\uDC38"), + ["\uDC38"]); + +// match after non-lead char +assertEqArray(/\u{DC38}/u.exec("\uDC38"), + ["\uDC38"]); +assertEqArray(/\u{DC38}/u.exec("A\uDC38"), + ["\uDC38"]); + +// ==== wrong patterns ==== + +assertThrowsInstanceOf(() => eval(`/\\u{-1}/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\u{0.0}/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\u{G}/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\u{}/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\u{{/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\u{/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\u{110000}/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\u{00110000}/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\u{100000000000000000000000000000}/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\u{FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF}/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\u{ FFFF}/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\u{FFFF }/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\u{FF FF}/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\u{F F F F}/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\u{100000001}/u`), SyntaxError); + +// surrogate pair with braced +assertEq(/\u{D83D}\u{DC38}+/u.exec("\uD83D\uDC38\uDC38"), + null); +assertEq(/\uD83D\u{DC38}+/u.exec("\uD83D\uDC38\uDC38"), + null); +assertEq(/\u{D83D}\uDC38+/u.exec("\uD83D\uDC38\uDC38"), + null); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/unicode-character-class-escape.js b/js/src/tests/non262/RegExp/unicode-character-class-escape.js new file mode 100644 index 0000000000..175207d5ae --- /dev/null +++ b/js/src/tests/non262/RegExp/unicode-character-class-escape.js @@ -0,0 +1,75 @@ +var BUGNUMBER = 1135377; +var summary = "Implement RegExp unicode flag -- CharacterClassEscape."; + +print(BUGNUMBER + ": " + summary); + +// BMP + +assertEqArray(/\d+/u.exec("abcxyzABCXYZ0123456789_\t\r\n\v\x0c\xa0\uFEFF*"), + ["0123456789"]); +assertEqArray(/\D+/u.exec("abcxyzABCXYZ0123456789_\t\r\n\v\x0c\xa0\uFEFF*"), + ["abcxyzABCXYZ"]); + +assertEqArray(/\s+/u.exec("abcxyzABCXYZ0123456789_\t\r\n\v\x0c\xa0\uFEFF*"), + ["\t\r\n\v\x0c\xa0\uFEFF"]); +assertEqArray(/\S+/u.exec("abcxyzABCXYZ0123456789_\t\r\n\v\x0c\xa0\uFEFF*"), + ["abcxyzABCXYZ0123456789_"]); + +assertEqArray(/\w+/u.exec("abcxyzABCXYZ0123456789_\t\r\n\v\x0c\xa0\uFEFF*"), + ["abcxyzABCXYZ0123456789_"]); +assertEqArray(/\W+/u.exec("abcxyzABCXYZ0123456789_\t\r\n\v\x0c\xa0\uFEFF*"), + ["\t\r\n\v\x0c\xa0\uFEFF*"]); + +assertEqArray(/\n+/u.exec("abcxyzABCXYZ0123456789_\t\r\n\v\x0c\xa0\uFEFF*"), + ["\n"]); + +assertEqArray(/[\d]+/u.exec("abcxyzABCXYZ0123456789_\t\r\n\v\x0c\xa0\uFEFF*"), + ["0123456789"]); +assertEqArray(/[\D]+/u.exec("abcxyzABCXYZ0123456789_\t\r\n\v\x0c\xa0\uFEFF*"), + ["abcxyzABCXYZ"]); + +assertEqArray(/[\s]+/u.exec("abcxyzABCXYZ0123456789_\t\r\n\v\x0c\xa0\uFEFF*"), + ["\t\r\n\v\x0c\xa0\uFEFF"]); +assertEqArray(/[\S]+/u.exec("abcxyzABCXYZ0123456789_\t\r\n\v\x0c\xa0\uFEFF*"), + ["abcxyzABCXYZ0123456789_"]); + +assertEqArray(/[\w]+/u.exec("abcxyzABCXYZ0123456789_\t\r\n\v\x0c\xa0\uFEFF*"), + ["abcxyzABCXYZ0123456789_"]); +assertEqArray(/[\W]+/u.exec("abcxyzABCXYZ0123456789_\t\r\n\v\x0c\xa0\uFEFF*"), + ["\t\r\n\v\x0c\xa0\uFEFF*"]); + +assertEqArray(/[\n]+/u.exec("abcxyzABCXYZ0123456789_\t\r\n\v\x0c\xa0\uFEFF*"), + ["\n"]); + +// non-BMP + +function testNonBMP(re) { + assertEqArray(re.exec("\uD83D\uDBFF"), + ["\uD83D"]); + assertEqArray(re.exec("\uD83D\uDC00"), + ["\uD83D\uDC00"]); + assertEqArray(re.exec("\uD83D\uDFFF"), + ["\uD83D\uDFFF"]); + assertEqArray(re.exec("\uD83D\uE000"), + ["\uD83D"]); + + assertEqArray(re.exec("\uD7FF\uDC38"), + ["\uD7FF"]); + assertEqArray(re.exec("\uD800\uDC38"), + ["\uD800\uDC38"]); + assertEqArray(re.exec("\uDBFF\uDC38"), + ["\uDBFF\uDC38"]); + assertEqArray(re.exec("\uDC00\uDC38"), + ["\uDC00"]); +} + +testNonBMP(/\D/u); +testNonBMP(/\S/u); +testNonBMP(/\W/u); + +testNonBMP(/[\D]/u); +testNonBMP(/[\S]/u); +testNonBMP(/[\W]/u); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/unicode-class-braced.js b/js/src/tests/non262/RegExp/unicode-class-braced.js new file mode 100644 index 0000000000..4b59540129 --- /dev/null +++ b/js/src/tests/non262/RegExp/unicode-class-braced.js @@ -0,0 +1,236 @@ +var BUGNUMBER = 1135377; +var summary = "Implement RegExp unicode flag -- braced pattern in RegExpUnicodeEscapeSequence in CharacterClass."; + +print(BUGNUMBER + ": " + summary); + +// ==== standalone ==== + +assertEqArray(/[\u{41}]/u.exec("ABC"), + ["A"]); + +assertEqArray(/[\u{1F438}]/u.exec("\u{1F438}"), + ["\u{1F438}"]); +assertEq(/[\u{1F438}]/u.exec("\uD83D"), + null); +assertEq(/[\u{1F438}]/u.exec("\uDC38"), + null); + +assertEqArray(/[\u{0}]/u.exec("\u{0}"), + ["\u{0}"]); +assertEqArray(/[\u{10FFFF}]/u.exec("\u{10FFFF}"), + ["\u{10FFFF}"]); +assertEqArray(/[\u{10ffff}]/u.exec("\u{10FFFF}"), + ["\u{10FFFF}"]); + +// leading 0 +assertEqArray(/[\u{0000000000000000000000}]/u.exec("\u{0}"), + ["\u{0}"]); +assertEqArray(/[\u{000000000000000010FFFF}]/u.exec("\u{10FFFF}"), + ["\u{10FFFF}"]); + +// RegExp constructor +assertEqArray(new RegExp("[\\u{0}]", "u").exec("\u{0}"), + ["\u{0}"]); +assertEqArray(new RegExp("[\\u{41}]", "u").exec("ABC"), + ["A"]); +assertEqArray(new RegExp("[\\u{1F438}]", "u").exec("\u{1F438}"), + ["\u{1F438}"]); +assertEqArray(new RegExp("[\\u{10FFFF}]", "u").exec("\u{10FFFF}"), + ["\u{10FFFF}"]); + +assertEqArray(new RegExp("[\\u{0000000000000000}]", "u").exec("\u{0}"), + ["\u{0}"]); + +assertEqArray(eval(`/[\\u{${"0".repeat(Math.pow(2, 24)) + "1234"}}]/u`).exec("\u{1234}"), + ["\u{1234}"]); +assertEqArray(new RegExp(`[\\u{${"0".repeat(Math.pow(2, 24)) + "1234"}}]`, "u").exec("\u{1234}"), + ["\u{1234}"]); + +// ==== BMP + non-BMP ==== + +assertEqArray(/[A\u{1F438}]/u.exec("A\u{1F438}"), + ["A"]); +assertEqArray(/[A\u{1F438}]/u.exec("\u{1F438}A"), + ["\u{1F438}"]); + +// lead-only target +assertEqArray(/[A\u{1F438}]/u.exec("\uD83DA"), + ["A"]); +assertEq(/[A\u{1F438}]/u.exec("\uD83D"), + null); + +// + +assertEqArray(/[A\u{1F438}]+/u.exec("\u{1F438}A\u{1F438}A"), + ["\u{1F438}A\u{1F438}A"]); + +// trail surrogate + lead surrogate +assertEqArray(/[A\u{1F438}]+/u.exec("\uD83D\uDC38A\uDC38\uD83DA"), + ["\uD83D\uDC38A"]); + +// ==== non-BMP + non-BMP ==== + +assertEqArray(/[\u{1F418}\u{1F438}]/u.exec("\u{1F418}\u{1F438}"), + ["\u{1F418}"]); + +assertEqArray(/[\u{1F418}\u{1F438}]+/u.exec("\u{1F418}\u{1F438}"), + ["\u{1F418}\u{1F438}"]); +assertEqArray(/[\u{1F418}\u{1F438}]+/u.exec("\u{1F418}\uDC38\uD83D"), + ["\u{1F418}"]); +assertEqArray(/[\u{1F418}\u{1F438}]+/u.exec("\uDC18\uD83D\u{1F438}"), + ["\u{1F438}"]); +assertEqArray(/[\u{1F418}\u{1F438}]+/u.exec("\uDC18\u{1F438}\uD83D"), + ["\u{1F438}"]); + +// trail surrogate + lead surrogate +assertEq(/[\u{1F418}\u{1F438}]+/u.exec("\uDC18\uDC38\uD83D\uD83D"), + null); + +// ==== non-BMP + non-BMP range (from_lead == to_lead) ==== + +assertEqArray(/[\u{1F418}-\u{1F438}]/u.exec("\u{1F418}"), + ["\u{1F418}"]); +assertEqArray(/[\u{1F418}-\u{1F438}]/u.exec("\u{1F438}"), + ["\u{1F438}"]); +assertEqArray(/[\u{1F418}-\u{1F438}]/u.exec("\u{1F427}"), + ["\u{1F427}"]); + +assertEq(/[\u{1F418}-\u{1F438}]/u.exec("\u{1F417}"), + null); +assertEq(/[\u{1F418}-\u{1F438}]/u.exec("\u{1F439}"), + null); + +// ==== non-BMP + non-BMP range (from_lead + 1 == to_lead) ==== + +assertEqArray(/[\u{1F17C}-\u{1F438}]/u.exec("\uD83C\uDD7C"), + ["\uD83C\uDD7C"]); +assertEqArray(/[\u{1F17C}-\u{1F438}]/u.exec("\u{1F438}"), + ["\u{1F438}"]); +assertEqArray(/[\u{1F17C}-\u{1F438}]/u.exec("\uD83C\uDF99"), + ["\uD83C\uDF99"]); +assertEqArray(/[\u{1F17C}-\u{1F438}]/u.exec("\uD83D\uDC00"), + ["\uD83D\uDC00"]); + +assertEq(/[\u{1F17C}-\u{1F438}]/u.exec("\uD83C\uDD7B"), + null); +assertEq(/[\u{1F17C}-\u{1F438}]/u.exec("\uD83C\uE000"), + null); +assertEq(/[\u{1F17C}-\u{1F438}]/u.exec("\uD83D\uDB99"), + null); +assertEq(/[\u{1F17C}-\u{1F438}]/u.exec("\uD83D\uDC39"), + null); + +// ==== non-BMP + non-BMP range (from_lead + 2 == to_lead) ==== + +assertEqArray(/[\u{1F17C}-\u{1F829}]/u.exec("\uD83C\uDD7C"), + ["\uD83C\uDD7C"]); +assertEqArray(/[\u{1F17C}-\u{1F829}]/u.exec("\uD83E\uDC29"), + ["\uD83E\uDC29"]); + +assertEqArray(/[\u{1F17C}-\u{1F829}]/u.exec("\uD83C\uDF99"), + ["\uD83C\uDF99"]); +assertEqArray(/[\u{1F17C}-\u{1F829}]/u.exec("\uD83D\uDC00"), + ["\uD83D\uDC00"]); +assertEqArray(/[\u{1F17C}-\u{1F829}]/u.exec("\uD83D\uDF99"), + ["\uD83D\uDF99"]); +assertEqArray(/[\u{1F17C}-\u{1F829}]/u.exec("\uD83E\uDC00"), + ["\uD83E\uDC00"]); + +assertEq(/[\u{1F17C}-\u{1F829}]/u.exec("\uD83C\uDD7B"), + null); +assertEq(/[\u{1F17C}-\u{1F829}]/u.exec("\uD83C\uE000"), + null); +assertEq(/[\u{1F17C}-\u{1F829}]/u.exec("\uD83D\uDB99"), + null); +assertEq(/[\u{1F17C}-\u{1F829}]/u.exec("\uD83D\uE000"), + null); +assertEq(/[\u{1F17C}-\u{1F829}]/u.exec("\uD83E\uDB99"), + null); +assertEq(/[\u{1F17C}-\u{1F829}]/u.exec("\uD83E\uDC30"), + null); + +// ==== non-BMP + non-BMP range (other) ==== + +assertEqArray(/[\u{1D164}-\u{1F438}]/u.exec("\uD834\uDD64"), + ["\uD834\uDD64"]); +assertEqArray(/[\u{1D164}-\u{1F438}]/u.exec("\u{1F438}"), + ["\u{1F438}"]); +assertEqArray(/[\u{1D164}-\u{1F438}]/u.exec("\uD836\uDF99"), + ["\uD836\uDF99"]); +assertEqArray(/[\u{1D164}-\u{1F438}]/u.exec("\uD838\uDC00"), + ["\uD838\uDC00"]); + +assertEq(/[\u{1D164}-\u{1F438}]/u.exec("\uD834\uDD63"), + null); +assertEq(/[\u{1D164}-\u{1F438}]/u.exec("\uD83D\uDC39"), + null); + +assertEq(/[\u{1D164}-\u{1F438}]/u.exec("\uD834\uE000"), + null); +assertEq(/[\u{1D164}-\u{1F438}]/u.exec("\uD835\uDB99"), + null); +assertEq(/[\u{1D164}-\u{1F438}]/u.exec("\uD83C\uE000"), + null); +assertEq(/[\u{1D164}-\u{1F438}]/u.exec("\uD83D\uDB99"), + null); + +// ==== BMP + non-BMP range ==== + +assertEqArray(/[\u{42}-\u{1F438}]/u.exec("B"), + ["B"]); +assertEqArray(/[\u{42}-\u{1F438}]/u.exec("C"), + ["C"]); +assertEqArray(/[\u{42}-\u{1F438}]/u.exec("\uFFFF"), + ["\uFFFF"]); +assertEqArray(/[\u{42}-\u{1F438}]/u.exec("\uD800\uDC00"), + ["\uD800\uDC00"]); + +assertEqArray(/[\u{42}-\u{1F438}]/u.exec("\uD800"), + ["\uD800"]); +assertEqArray(/[\u{42}-\u{1F438}]/u.exec("\uDBFF"), + ["\uDBFF"]); +assertEqArray(/[\u{42}-\u{1F438}]/u.exec("\uDC00"), + ["\uDC00"]); +assertEqArray(/[\u{42}-\u{1F438}]/u.exec("\uDFFF"), + ["\uDFFF"]); + +assertEqArray(/[\u{42}-\u{1F438}]/u.exec("\uD83D"), + ["\uD83D"]); +assertEqArray(/[\u{42}-\u{1F438}]/u.exec("\uDC38"), + ["\uDC38"]); + +assertEqArray(/[\u{42}-\u{1F438}]/u.exec("\uD83D\uDBFF"), + ["\uD83D"]); +assertEqArray(/[\u{42}-\u{1F438}]/u.exec("\uD83D\uDC00"), + ["\uD83D\uDC00"]); +assertEqArray(/[\u{42}-\u{1F438}]/u.exec("\uD83D\uDC38"), + ["\uD83D\uDC38"]); +assertEq(/[\u{42}-\u{1F438}]/u.exec("\uD83D\uDC39"), + null); +assertEq(/[\u{42}-\u{1F438}]/u.exec("\uD83D\uDFFF"), + null); +assertEqArray(/[\u{42}-\u{1F438}]/u.exec("\uD83D\uE000"), + ["\uD83D"]); + +assertEq(/[\u{42}-\u{1F438}]/u.exec("A"), + null); + +// ==== wrong patterns ==== + +assertThrowsInstanceOf(() => eval(`/[\\u{-1}]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\u{0.0}]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\u{G}]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\u{}]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\u{{]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\u{]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\u{110000}]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\u{00110000}]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\u{100000000000000000000000000000}]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\u{FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF}]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\u{ FFFF}]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\u{FFFF }]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\u{FF FF}]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\u{F F F F}]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\u{100000001}]/u`), SyntaxError); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/unicode-class-empty.js b/js/src/tests/non262/RegExp/unicode-class-empty.js new file mode 100644 index 0000000000..4d187551f6 --- /dev/null +++ b/js/src/tests/non262/RegExp/unicode-class-empty.js @@ -0,0 +1,25 @@ +var BUGNUMBER = 1135377; +var summary = "Implement RegExp unicode flag -- empty class should not match anything."; + +print(BUGNUMBER + ": " + summary); + +assertEq(/[]/u.exec("A"), + null); +assertEq(/[]/u.exec("\uD83D"), + null); +assertEq(/[]/u.exec("\uDC38"), + null); +assertEq(/[]/u.exec("\uD83D\uDC38"), + null); + +assertEqArray(/[^]/u.exec("A"), + ["A"]); +assertEqArray(/[^]/u.exec("\uD83D"), + ["\uD83D"]); +assertEqArray(/[^]/u.exec("\uDC38"), + ["\uDC38"]); +assertEqArray(/[^]/u.exec("\uD83D\uDC38"), + ["\uD83D\uDC38"]); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/unicode-class-ignoreCase.js b/js/src/tests/non262/RegExp/unicode-class-ignoreCase.js new file mode 100644 index 0000000000..afa7705c72 --- /dev/null +++ b/js/src/tests/non262/RegExp/unicode-class-ignoreCase.js @@ -0,0 +1,28 @@ +var BUGNUMBER = 1135377; +var summary = "Implement RegExp unicode flag -- ignoreCase flag for CharacterClass."; + +print(BUGNUMBER + ": " + summary); + +assertEqArray(/[ABC]+/iu.exec("DCBAabcd"), + ["CBAabc"]); + +assertEqArray(/[A\u{10401}]+/iu.exec("A\u{10401}a\u{10429}"), + ["A\u{10401}a\u{10429}"]); + +assertEqArray(/[\u{10401}-\u{10404}\u{10408}-\u{1040B}]+/iu.exec("\u{10400}\u{10401}\u{10402}\u{10403}\u{10404}\u{10408}\u{10409}\u{1040A}\u{1040B}\u{1040C}"), + ["\u{10401}\u{10402}\u{10403}\u{10404}\u{10408}\u{10409}\u{1040A}\u{1040B}"]); +assertEqArray(/[\u{10401}-\u{10404}\u{10408}-\u{1040B}]+/iu.exec("\u{10428}\u{10429}\u{1042A}\u{1042B}\u{1042C}\u{10430}\u{10431}\u{10432}\u{10433}\u{10434}"), + ["\u{10429}\u{1042A}\u{1042B}\u{1042C}\u{10430}\u{10431}\u{10432}\u{10433}"]); + +assertEqArray(/[\u{10429}-\u{1042C}\u{10430}-\u{10433}]+/iu.exec("\u{10400}\u{10401}\u{10402}\u{10403}\u{10404}\u{10408}\u{10409}\u{1040A}\u{1040B}\u{1040C}"), + ["\u{10401}\u{10402}\u{10403}\u{10404}\u{10408}\u{10409}\u{1040A}\u{1040B}"]); +assertEqArray(/[\u{10429}-\u{1042C}\u{10430}-\u{10433}]+/iu.exec("\u{10428}\u{10429}\u{1042A}\u{1042B}\u{1042C}\u{10430}\u{10431}\u{10432}\u{10433}\u{10434}"), + ["\u{10429}\u{1042A}\u{1042B}\u{1042C}\u{10430}\u{10431}\u{10432}\u{10433}"]); + +assertEqArray(/[\u{10401}-\u{10404}\u{10430}-\u{10433}]+/iu.exec("\u{10400}\u{10401}\u{10402}\u{10403}\u{10404}\u{10408}\u{10409}\u{1040A}\u{1040B}\u{1040C}"), + ["\u{10401}\u{10402}\u{10403}\u{10404}\u{10408}\u{10409}\u{1040A}\u{1040B}"]); +assertEqArray(/[\u{10401}-\u{10404}\u{10430}-\u{10433}]+/iu.exec("\u{10428}\u{10429}\u{1042A}\u{1042B}\u{1042C}\u{10430}\u{10431}\u{10432}\u{10433}\u{10434}"), + ["\u{10429}\u{1042A}\u{1042B}\u{1042C}\u{10430}\u{10431}\u{10432}\u{10433}"]); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/unicode-class-lead-trail.js b/js/src/tests/non262/RegExp/unicode-class-lead-trail.js new file mode 100644 index 0000000000..c83bf937d4 --- /dev/null +++ b/js/src/tests/non262/RegExp/unicode-class-lead-trail.js @@ -0,0 +1,142 @@ +var BUGNUMBER = 1135377; +var summary = "Implement RegExp unicode flag -- lead and trail pattern in RegExpUnicodeEscapeSequence in CharacterClass."; + +print(BUGNUMBER + ": " + summary); + +// ==== standalone ==== + +assertEqArray(/[\uD83D\uDC38]/u.exec("\uD83D\uDC38"), + ["\uD83D\uDC38"]); +assertEq(/[\uD83D\uDC38]/u.exec("\uD83D"), + null); +assertEq(/[\uD83D\uDC38]/u.exec("\uDC38"), + null); + +// no unicode flag +assertEqArray(/[\uD83D\uDC38]/.exec("\uD83D\uDC38"), + ["\uD83D"]); +assertEqArray(/[\uD83D\uDC38]/.exec("\uD83D"), + ["\uD83D"]); +assertEqArray(/[\uD83D\uDC38]/.exec("\uDC38"), + ["\uDC38"]); + +// RegExp constructor +assertEqArray(new RegExp("[\uD83D\uDC38]", "u").exec("\uD83D\uDC38"), + ["\uD83D\uDC38"]); +assertEq(new RegExp("[\uD83D\uDC38]", "u").exec("\uD83D"), + null); +assertEq(new RegExp("[\uD83D\uDC38]", "u").exec("\uDC38"), + null); + +// RegExp constructor, no unicode flag +assertEqArray(new RegExp("[\uD83D\uDC38]", "").exec("\uD83D\uDC38"), + ["\uD83D"]); +assertEqArray(new RegExp("[\uD83D\uDC38]", "").exec("\uD83D"), + ["\uD83D"]); +assertEqArray(new RegExp("[\uD83D\uDC38]", "").exec("\uDC38"), + ["\uDC38"]); + +// ==== lead-only ==== + +// match only non-surrogate pair +assertEqArray(/[\uD83D]/u.exec("\uD83D\uDBFF"), + ["\uD83D"]); +assertEq(/[\uD83D]/u.exec("\uD83D\uDC00"), + null); +assertEq(/[\uD83D]/u.exec("\uD83D\uDFFF"), + null); +assertEqArray(/[\uD83D]/u.exec("\uD83D\uE000"), + ["\uD83D"]); + +// match before non-tail char +assertEqArray(/[\uD83D]/u.exec("\uD83D"), + ["\uD83D"]); +assertEqArray(/[\uD83D]/u.exec("\uD83DA"), + ["\uD83D"]); + +// no unicode flag +assertEqArray(/[\uD83D]/.exec("\uD83D\uDBFF"), + ["\uD83D"]); +assertEqArray(/[\uD83D]/.exec("\uD83D\uDC00"), + ["\uD83D"]); +assertEqArray(/[\uD83D]/.exec("\uD83D\uDFFF"), + ["\uD83D"]); +assertEqArray(/[\uD83D]/.exec("\uD83D\uE000"), + ["\uD83D"]); +assertEqArray(/[\uD83D]/.exec("\uD83D"), + ["\uD83D"]); +assertEqArray(/[\uD83D]/.exec("\uD83DA"), + ["\uD83D"]); + +// ==== trail-only ==== + +// match only non-surrogate pair +assertEqArray(/[\uDC38]/u.exec("\uD7FF\uDC38"), + ["\uDC38"]); +assertEq(/[\uDC38]/u.exec("\uD800\uDC38"), + null); +assertEq(/[\uDC38]/u.exec("\uDBFF\uDC38"), + null); +assertEqArray(/[\uDC38]/u.exec("\uDC00\uDC38"), + ["\uDC38"]); + +// match after non-lead char +assertEqArray(/[\uDC38]/u.exec("\uDC38"), + ["\uDC38"]); +assertEqArray(/[\uDC38]/u.exec("A\uDC38"), + ["\uDC38"]); + +// no unicode flag +assertEqArray(/[\uDC38]/.exec("\uD7FF\uDC38"), + ["\uDC38"]); +assertEqArray(/[\uDC38]/.exec("\uD800\uDC38"), + ["\uDC38"]); +assertEqArray(/[\uDC38]/.exec("\uDBFF\uDC38"), + ["\uDC38"]); +assertEqArray(/[\uDC38]/.exec("\uDC00\uDC38"), + ["\uDC38"]); +assertEqArray(/[\uDC38]/.exec("\uDC38"), + ["\uDC38"]); +assertEqArray(/[\uDC38]/.exec("A\uDC38"), + ["\uDC38"]); + +// ==== invalid trail ==== + +assertEqArray(/[\uD83D\u3042]*/u.exec("\uD83D"), + ["\uD83D"]); +assertEqArray(/[\uD83D\u3042]*/u.exec("\uD83D\u3042"), + ["\uD83D\u3042"]); +assertEqArray(/[\uD83D\u3042]*/u.exec("\uD83D\u3042\u3042\uD83D"), + ["\uD83D\u3042\u3042\uD83D"]); + +assertEqArray(/[\uD83D\u{3042}]*/u.exec("\uD83D"), + ["\uD83D"]); +assertEqArray(/[\uD83D\u{3042}]*/u.exec("\uD83D\u3042"), + ["\uD83D\u3042"]); +assertEqArray(/[\uD83D\u{3042}]*/u.exec("\uD83D\u3042\u3042\uD83D"), + ["\uD83D\u3042\u3042\uD83D"]); + +assertEqArray(/[\uD83DA]*/u.exec("\uD83D"), + ["\uD83D"]); +assertEqArray(/[\uD83DA]*/u.exec("\uD83DA"), + ["\uD83DA"]); +assertEqArray(/[\uD83DA]*/u.exec("\uD83DAA\uD83D"), + ["\uD83DAA\uD83D"]); + +// ==== wrong patterns ==== + +assertThrowsInstanceOf(() => eval(`/[\\u]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\u0]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\u00]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\u000]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\u000G]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\u0.00]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\uD83D\\u]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\uD83D\\u0]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\uD83D\\u00]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\uD83D\\u000]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\uD83D\\u000G]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\uD83D\\u0.00]/u`), SyntaxError); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/unicode-class-negated.js b/js/src/tests/non262/RegExp/unicode-class-negated.js new file mode 100644 index 0000000000..0b573f6dcf --- /dev/null +++ b/js/src/tests/non262/RegExp/unicode-class-negated.js @@ -0,0 +1,64 @@ +var BUGNUMBER = 1135377; +var summary = "Implement RegExp unicode flag -- negated CharacterClass."; + +print(BUGNUMBER + ": " + summary); + +// ==== BMP ==== + +assertEqArray(/[^A]/u.exec("ABC"), + ["B"]); +assertEqArray(/[^A]/u.exec("A\u{1F438}C"), + ["\u{1F438}"]); +assertEqArray(/[^A]/u.exec("A\uD83DC"), + ["\uD83D"]); +assertEqArray(/[^A]/u.exec("A\uDC38C"), + ["\uDC38"]); + +assertEqArray(/[^\uE000]/u.exec("\uE000\uE001"), + ["\uE001"]); +assertEqArray(/[^\uE000]/u.exec("\uE000\u{1F438}"), + ["\u{1F438}"]); +assertEqArray(/[^\uE000]/u.exec("\uE000\uD83D"), + ["\uD83D"]); +assertEqArray(/[^\uE000]/u.exec("\uE000\uDC38"), + ["\uDC38"]); + +// ==== non-BMP ==== + +assertEqArray(/[^\u{1F438}]/u.exec("\u{1F438}A"), + ["A"]); +assertEqArray(/[^\u{1F438}]/u.exec("\u{1F438}\u{1F439}"), + ["\u{1F439}"]); +assertEqArray(/[^\u{1F438}]/u.exec("\u{1F438}\uD83D"), + ["\uD83D"]); +assertEqArray(/[^\u{1F438}]/u.exec("\u{1F438}\uDC38"), + ["\uDC38"]); + +// ==== lead-only ==== + +assertEqArray(/[^\uD83D]/u.exec("\u{1F438}A"), + ["\u{1F438}"]); +assertEqArray(/[^\uD83D]/u.exec("\uD83D\uDBFF"), + ["\uDBFF"]); +assertEqArray(/[^\uD83D]/u.exec("\uD83D\uDC00"), + ["\uD83D\uDC00"]); +assertEqArray(/[^\uD83D]/u.exec("\uD83D\uDFFF"), + ["\uD83D\uDFFF"]); +assertEqArray(/[^\uD83D]/u.exec("\uD83D\uE000"), + ["\uE000"]); + +// ==== trail-only ==== + +assertEqArray(/[^\uDC38]/u.exec("\u{1F438}A"), + ["\u{1F438}"]); +assertEqArray(/[^\uDC38]/u.exec("\uD7FF\uDC38"), + ["\uD7FF"]); +assertEqArray(/[^\uDC38]/u.exec("\uD800\uDC38"), + ["\uD800\uDC38"]); +assertEqArray(/[^\uDC38]/u.exec("\uDBFF\uDC38"), + ["\uDBFF\uDC38"]); +assertEqArray(/[^\uDC38]/u.exec("\uDC00\uDC38"), + ["\uDC00"]); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/unicode-class-range.js b/js/src/tests/non262/RegExp/unicode-class-range.js new file mode 100644 index 0000000000..5bb7575601 --- /dev/null +++ b/js/src/tests/non262/RegExp/unicode-class-range.js @@ -0,0 +1,28 @@ +var BUGNUMBER = 1135377; +var summary = "Implement RegExp unicode flag -- disallow range with CharacterClassEscape."; + +print(BUGNUMBER + ": " + summary); + +assertThrowsInstanceOf(() => eval(`/[\\w-\\uFFFF]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\W-\\uFFFF]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\d-\\uFFFF]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\D-\\uFFFF]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\s-\\uFFFF]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\S-\\uFFFF]/u`), SyntaxError); + +assertThrowsInstanceOf(() => eval(`/[\\uFFFF-\\w]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\uFFFF-\\W]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\uFFFF-\\d]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\uFFFF-\\D]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\uFFFF-\\s]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\uFFFF-\\S]/u`), SyntaxError); + +assertThrowsInstanceOf(() => eval(`/[\\w-\\w]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\W-\\W]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\d-\\d]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\D-\\D]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\s-\\s]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\S-\\S]/u`), SyntaxError); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/unicode-class-raw.js b/js/src/tests/non262/RegExp/unicode-class-raw.js new file mode 100644 index 0000000000..742fec2b4d --- /dev/null +++ b/js/src/tests/non262/RegExp/unicode-class-raw.js @@ -0,0 +1,65 @@ +var BUGNUMBER = 1135377; +var summary = "Implement RegExp unicode flag -- raw unicode."; + +print(BUGNUMBER + ": " + summary); + +// ==== standalone ==== + +assertEqArray(eval(`/[\uD83D\uDC38]/u`).exec("\u{1F438}"), + ["\u{1F438}"]); + +// no unicode flag +assertEqArray(eval(`/[\uD83D\uDC38]/`).exec("\u{1F438}"), + ["\uD83D"]); + +// escaped (lead) +assertEq(eval(`/[\\uD83D\uDC38]/u`).exec("\u{1F438}"), + null); +assertEq(eval(`/[\\u{D83D}\uDC38]/u`).exec("\u{1F438}"), + null); + +// escaped (trail) +assertEq(eval(`/[\uD83D\\uDC38]/u`).exec("\u{1F438}"), + null); +assertEq(eval(`/[\uD83D\\u{DC38}]/u`).exec("\u{1F438}"), + null); + +// escaped (lead), no unicode flag +assertEqArray(eval(`/[\\uD83D\uDC38]/`).exec("\u{1F438}"), + ["\uD83D"]); + +// escaped (trail), no unicode flag +assertEqArray(eval(`/[\uD83D\\uDC38]/`).exec("\u{1F438}"), + ["\uD83D"]); + +// ==== RegExp constructor ==== + +assertEqArray(new RegExp("[\uD83D\uDC38]", "u").exec("\u{1F438}"), + ["\u{1F438}"]); + +// no unicode flag +assertEqArray(new RegExp("[\uD83D\uDC38]", "").exec("\u{1F438}"), + ["\uD83D"]); + +// escaped(lead) +assertEq(new RegExp("[\\uD83D\uDC38]", "u").exec("\u{1F438}"), + null); +assertEq(new RegExp("[\\u{D83D}\uDC38]", "u").exec("\u{1F438}"), + null); + +// escaped(trail) +assertEq(new RegExp("[\uD83D\\uDC38]", "u").exec("\u{1F438}"), + null); +assertEq(new RegExp("[\uD83D\\u{DC38}]", "u").exec("\u{1F438}"), + null); + +// escaped(lead), no unicode flag +assertEqArray(new RegExp("[\\uD83D\uDC38]", "").exec("\u{1F438}"), + ["\uD83D"]); + +// escaped(trail), no unicode flag +assertEqArray(new RegExp("[\uD83D\\uDC38]", "").exec("\u{1F438}"), + ["\uD83D"]); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/unicode-disallow-extended.js b/js/src/tests/non262/RegExp/unicode-disallow-extended.js new file mode 100644 index 0000000000..01d5d244e1 --- /dev/null +++ b/js/src/tests/non262/RegExp/unicode-disallow-extended.js @@ -0,0 +1,139 @@ +var BUGNUMBER = 1135377; +var summary = "Implement RegExp unicode flag -- disallow extended patterns."; + +print(BUGNUMBER + ": " + summary); + +// IdentityEscape + +assertEqArray(/\^\$\\\.\*\+\?\(\)\[\]\{\}\|/u.exec("^$\\.*+?()[]{}|"), + ["^$\\.*+?()[]{}|"]); +assertThrowsInstanceOf(() => eval(`/\\A/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\-/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\U{10}/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\U0000/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\uD83D\\U0000/u`), SyntaxError); + +assertEqArray(/[\^\$\\\.\*\+\?\(\)\[\]\{\}\|]+/u.exec("^$\\.*+?()[]{}|"), + ["^$\\.*+?()[]{}|"]); +assertThrowsInstanceOf(() => eval(`/[\\A]/u`), SyntaxError); +assertEqArray(/[A\-Z]+/u.exec("a-zABC"), + ["-"]); +assertThrowsInstanceOf(() => eval(`/[\\U{10}]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\U0000]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\uD83D\\U0000]/u`), SyntaxError); + +// PatternCharacter +assertThrowsInstanceOf(() => eval(`/{}/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/{/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/}/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/{0}/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/{1,}/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/{1,2}/u`), SyntaxError); + +// QuantifiableAssertion +assertEqArray(/.B(?=A)/u.exec("cBaCBA"), + ["CB"]); +assertEqArray(/.B(?!A)/u.exec("CBAcBa"), + ["cB"]); +assertEqArray(/.B(?:A)/u.exec("cBaCBA"), + ["CBA"]); +assertEqArray(/.B(A)/u.exec("cBaCBA"), + ["CBA", "A"]); + +assertThrowsInstanceOf(() => eval(`/.B(?=A)+/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/.B(?!A)+/u`), SyntaxError); +assertEqArray(/.B(?:A)+/u.exec("cBaCBA"), + ["CBA"]); +assertEqArray(/.B(A)+/u.exec("cBaCBA"), + ["CBA", "A"]); + +// ControlLetter +assertEqArray(/\cA/u.exec("\u0001"), + ["\u0001"]); +assertEqArray(/\cZ/u.exec("\u001a"), + ["\u001a"]); +assertEqArray(/\ca/u.exec("\u0001"), + ["\u0001"]); +assertEqArray(/\cz/u.exec("\u001a"), + ["\u001a"]); + +assertEqArray(/[\cA]/u.exec("\u0001"), + ["\u0001"]); +assertEqArray(/[\cZ]/u.exec("\u001a"), + ["\u001a"]); +assertEqArray(/[\ca]/u.exec("\u0001"), + ["\u0001"]); +assertEqArray(/[\cz]/u.exec("\u001a"), + ["\u001a"]); + +assertThrowsInstanceOf(() => eval(`/\\c/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\c1/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\c_/u`), SyntaxError); + +assertThrowsInstanceOf(() => eval(`/[\\c]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\c1]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\c_]/u`), SyntaxError); + +// HexEscapeSequence +assertThrowsInstanceOf(() => eval(`/\\x/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\x0/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\x1/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\x1G/u`), SyntaxError); + +assertThrowsInstanceOf(() => eval(`/[\\x]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\x0]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\x1]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\x1G]/u`), SyntaxError); + +// LegacyOctalEscapeSequence +assertThrowsInstanceOf(() => eval(`/\\52/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\052/u`), SyntaxError); + +assertThrowsInstanceOf(() => eval(`/[\\52]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\052]/u`), SyntaxError); + +// DecimalEscape +assertEqArray(/\0/u.exec("\0"), + ["\0"]); +assertEqArray(/[\0]/u.exec("\0"), + ["\0"]); +assertEqArray(/\0A/u.exec("\0A"), + ["\0A"]); +assertEqArray(/\0G/u.exec("\0G"), + ["\0G"]); +assertEqArray(/(A.)\1/u.exec("ABACABAB"), + ["ABAB", "AB"]); +assertEqArray(/(A.)(B.)(C.)(D.)(E.)(F.)(G.)(H.)(I.)(J.)(K.)\10/u.exec("A1B2C3D4E5F6G7H8I9JaKbJa"), + ["A1B2C3D4E5F6G7H8I9JaKbJa", "A1", "B2", "C3", "D4", "E5", "F6", "G7", "H8", "I9", "Ja", "Kb"]); + +assertThrowsInstanceOf(() => eval(`/\\00/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\01/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\09/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\1/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\2/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\3/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\4/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\5/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\6/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\7/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\8/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\9/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\10/u`), SyntaxError); + +assertThrowsInstanceOf(() => eval(`/[\\00]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\01]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\09]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\1]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\2]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\3]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\4]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\5]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\6]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\7]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\8]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\9]/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/[\\10]/u`), SyntaxError); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/unicode-everything.js b/js/src/tests/non262/RegExp/unicode-everything.js new file mode 100644 index 0000000000..a18ac2867a --- /dev/null +++ b/js/src/tests/non262/RegExp/unicode-everything.js @@ -0,0 +1,59 @@ +var BUGNUMBER = 1135377; +var summary = "Implement RegExp unicode flag -- everything Atom."; + +print(BUGNUMBER + ": " + summary); + +// ==== standalone ==== + +assertEqArray(/./u.exec("ABC"), + ["A"]); +assertEqArray(/./u.exec("\u{1F438}BC"), + ["\u{1F438}"]); + +assertEqArray(/./u.exec("\uD83D\uDBFF"), + ["\uD83D"]); +assertEqArray(/./u.exec("\uD83D\uDC00"), + ["\uD83D\uDC00"]); +assertEqArray(/./u.exec("\uD83D\uDFFF"), + ["\uD83D\uDFFF"]); +assertEqArray(/./u.exec("\uD83D\uE000"), + ["\uD83D"]); +assertEqArray(/./u.exec("\uD83D"), + ["\uD83D"]); +assertEqArray(/./u.exec("\uD83DA"), + ["\uD83D"]); + +assertEqArray(/./u.exec("\uD7FF\uDC38"), + ["\uD7FF"]); +assertEqArray(/./u.exec("\uD800\uDC38"), + ["\uD800\uDC38"]); +assertEqArray(/./u.exec("\uDBFF\uDC38"), + ["\uDBFF\uDC38"]); +assertEqArray(/./u.exec("\uDC00\uDC38"), + ["\uDC00"]); +assertEqArray(/./u.exec("\uDC38"), + ["\uDC38"]); +assertEqArray(/./u.exec("A\uDC38"), + ["A"]); + +assertEqArray(/.A/u.exec("\uD7FF\uDC38A"), + ["\uDC38A"]); +assertEqArray(/.A/u.exec("\uD800\uDC38A"), + ["\uD800\uDC38A"]); +assertEqArray(/.A/u.exec("\uDBFF\uDC38A"), + ["\uDBFF\uDC38A"]); +assertEqArray(/.A/u.exec("\uDC00\uDC38A"), + ["\uDC38A"]); + +// ==== leading multiple ==== + +assertEqArray(/.*A/u.exec("\u{1F438}\u{1F438}\u{1F438}A"), + ["\u{1F438}\u{1F438}\u{1F438}A"]); + +// ==== trailing multiple ==== + +assertEqArray(/A.*/u.exec("A\u{1F438}\u{1F438}\u{1F438}"), + ["A\u{1F438}\u{1F438}\u{1F438}"]); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/unicode-ignoreCase-ascii.js b/js/src/tests/non262/RegExp/unicode-ignoreCase-ascii.js new file mode 100644 index 0000000000..6d453290e9 --- /dev/null +++ b/js/src/tests/non262/RegExp/unicode-ignoreCase-ascii.js @@ -0,0 +1,45 @@ +var BUGNUMBER = 1135377; +var summary = "Implement RegExp unicode flag -- ignoreCase flag with non-ascii to ascii map."; + +print(BUGNUMBER + ": " + summary); + +// LATIN CAPITAL LETTER Y WITH DIAERESIS +assertEqArray(/\u0178/iu.exec("\u00FF"), + ["\u00FF"]); +assertEqArray(/\u00FF/iu.exec("\u0178"), + ["\u0178"]); + +// LATIN SMALL LETTER LONG S +assertEqArray(/\u017F/iu.exec("S"), + ["S"]); +assertEqArray(/\u017F/iu.exec("s"), + ["s"]); +assertEqArray(/S/iu.exec("\u017F"), + ["\u017F"]); +assertEqArray(/s/iu.exec("\u017F"), + ["\u017F"]); + +// LATIN CAPITAL LETTER SHARP S +assertEqArray(/\u1E9E/iu.exec("\u00DF"), + ["\u00DF"]); +assertEqArray(/\u00DF/iu.exec("\u1E9E"), + ["\u1E9E"]); + +// KELVIN SIGN +assertEqArray(/\u212A/iu.exec("K"), + ["K"]); +assertEqArray(/\u212A/iu.exec("k"), + ["k"]); +assertEqArray(/K/iu.exec("\u212A"), + ["\u212A"]); +assertEqArray(/k/iu.exec("\u212A"), + ["\u212A"]); + +// ANGSTROM SIGN +assertEqArray(/\u212B/iu.exec("\u00E5"), + ["\u00E5"]); +assertEqArray(/\u00E5/iu.exec("\u212B"), + ["\u212B"]); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/unicode-ignoreCase-escape.js b/js/src/tests/non262/RegExp/unicode-ignoreCase-escape.js new file mode 100644 index 0000000000..d731fb6bbe --- /dev/null +++ b/js/src/tests/non262/RegExp/unicode-ignoreCase-escape.js @@ -0,0 +1,71 @@ +var BUGNUMBER = 1135377; +var summary = "Implement RegExp unicode flag -- ignoreCase flag with character class escape."; + +// \W doesn't match S or K from the change in +// https://github.com/tc39/ecma262/pull/525 +// (bug 1281739) + +print(BUGNUMBER + ": " + summary); + +// LATIN SMALL LETTER LONG S + +assertEqArray(/\w/iu.exec("S"), + ["S"]); +assertEqArray(/\w/iu.exec("s"), + ["s"]); +assertEqArray(/\w/iu.exec("\u017F"), + ["\u017F"]); + +assertEqArray(/[^\W]/iu.exec("S"), + ["S"]); +assertEqArray(/[^\W]/iu.exec("s"), + ["s"]); +assertEqArray(/[^\W]/iu.exec("\u017F"), + ["\u017F"]); + +assertEq(/\W/iu.exec("S"), + null); +assertEq(/\W/iu.exec("s"), + null); +assertEq(/\W/iu.exec("\u017F"), + null); + +assertEq(/[^\w]/iu.exec("S"), + null); +assertEq(/[^\w]/iu.exec("s"), + null); +assertEq(/[^\w]/iu.exec("\u017F"), + null); + +// KELVIN SIGN + +assertEqArray(/\w/iu.exec("k"), + ["k"]); +assertEqArray(/\w/iu.exec("k"), + ["k"]); +assertEqArray(/\w/iu.exec("\u212A"), + ["\u212A"]); + +assertEqArray(/[^\W]/iu.exec("k"), + ["k"]); +assertEqArray(/[^\W]/iu.exec("k"), + ["k"]); +assertEqArray(/[^\W]/iu.exec("\u212A"), + ["\u212A"]); + +assertEq(/\W/iu.exec("k"), + null); +assertEq(/\W/iu.exec("k"), + null); +assertEq(/\W/iu.exec("\u212A"), + null); + +assertEq(/[^\w]/iu.exec("k"), + null); +assertEq(/[^\w]/iu.exec("k"), + null); +assertEq(/[^\w]/iu.exec("\u212A"), + null); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/unicode-ignoreCase-negated.js b/js/src/tests/non262/RegExp/unicode-ignoreCase-negated.js new file mode 100644 index 0000000000..30909a515a --- /dev/null +++ b/js/src/tests/non262/RegExp/unicode-ignoreCase-negated.js @@ -0,0 +1,19 @@ +var BUGNUMBER = 1135377; +var summary = "Implement RegExp unicode flag -- ignoreCase flag with negated character class."; + +print(BUGNUMBER + ": " + summary); + +assertEq(/[^A]/iu.exec("A"), + null); +assertEq(/[^a]/iu.exec("A"), + null); +assertEq(/[^A]/iu.exec("a"), + null); +assertEq(/[^a]/iu.exec("a"), + null); + +assertEqArray(/[^A]/iu.exec("b"), + ["b"]); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/unicode-ignoreCase-word-boundary.js b/js/src/tests/non262/RegExp/unicode-ignoreCase-word-boundary.js new file mode 100644 index 0000000000..a5698de365 --- /dev/null +++ b/js/src/tests/non262/RegExp/unicode-ignoreCase-word-boundary.js @@ -0,0 +1,46 @@ +var BUGNUMBER = 1338373; +var summary = "Word boundary should match U+017F and U+212A in unicode+ignoreCase."; + +assertEq(/\b/iu.test('\u017F'), true); +assertEq(/\b/i.test('\u017F'), false); +assertEq(/\b/u.test('\u017F'), false); +assertEq(/\b/.test('\u017F'), false); + +assertEq(/\b/iu.test('\u212A'), true); +assertEq(/\b/i.test('\u212A'), false); +assertEq(/\b/u.test('\u212A'), false); +assertEq(/\b/.test('\u212A'), false); + +assertEq(/\B/iu.test('\u017F'), false); +assertEq(/\B/i.test('\u017F'), true); +assertEq(/\B/u.test('\u017F'), true); +assertEq(/\B/.test('\u017F'), true); + +assertEq(/\B/iu.test('\u212A'), false); +assertEq(/\B/i.test('\u212A'), true); +assertEq(/\B/u.test('\u212A'), true); +assertEq(/\B/.test('\u212A'), true); + +// Bug 1338779 - More testcases. +assertEq(/(i\B\u017F)/ui.test("is"), true); +assertEq(/(i\B\u017F)/ui.test("it"), false); +assertEq(/(i\B\u017F)+/ui.test("is"), true); +assertEq(/(i\B\u017F)+/ui.test("it"), false); + +assertEq(/(\u017F\Bi)/ui.test("si"), true); +assertEq(/(\u017F\Bi)/ui.test("ti"), false); +assertEq(/(\u017F\Bi)+/ui.test("si"), true); +assertEq(/(\u017F\Bi)+/ui.test("ti"), false); + +assertEq(/(i\B\u212A)/ui.test("ik"), true); +assertEq(/(i\B\u212A)/ui.test("it"), false); +assertEq(/(i\B\u212A)+/ui.test("ik"), true); +assertEq(/(i\B\u212A)+/ui.test("it"), false); + +assertEq(/(\u212A\Bi)/ui.test("ki"), true); +assertEq(/(\u212A\Bi)/ui.test("ti"), false); +assertEq(/(\u212A\Bi)+/ui.test("ki"), true); +assertEq(/(\u212A\Bi)+/ui.test("ti"), false); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/unicode-ignoreCase.js b/js/src/tests/non262/RegExp/unicode-ignoreCase.js new file mode 100644 index 0000000000..2cf489f310 --- /dev/null +++ b/js/src/tests/non262/RegExp/unicode-ignoreCase.js @@ -0,0 +1,2901 @@ +/* Generated by make_unicode.py DO NOT MODIFY */ +/* Unicode version: 15.0.0 */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 1135377; +var summary = "Implement RegExp unicode flag -- ignoreCase flag."; + +print(BUGNUMBER + ": " + summary); + +function test(code, ...equivs) { + var codeRe = new RegExp(String.fromCodePoint(code) + "+", "iu"); + var ans = String.fromCodePoint(code) + equivs.map(c => String.fromCodePoint(c)).join(""); + assertEqArray(codeRe.exec("<" + ans + ">"), [ans]); + codeRe = new RegExp("[" + String.fromCodePoint(code) + "]+", "iu"); + assertEqArray(codeRe.exec("<" + ans + ">"), [ans]); +} +test(0x0041, 0x0061); // LATIN CAPITAL LETTER A, LATIN SMALL LETTER A +test(0x0042, 0x0062); // LATIN CAPITAL LETTER B, LATIN SMALL LETTER B +test(0x0043, 0x0063); // LATIN CAPITAL LETTER C, LATIN SMALL LETTER C +test(0x0044, 0x0064); // LATIN CAPITAL LETTER D, LATIN SMALL LETTER D +test(0x0045, 0x0065); // LATIN CAPITAL LETTER E, LATIN SMALL LETTER E +test(0x0046, 0x0066); // LATIN CAPITAL LETTER F, LATIN SMALL LETTER F +test(0x0047, 0x0067); // LATIN CAPITAL LETTER G, LATIN SMALL LETTER G +test(0x0048, 0x0068); // LATIN CAPITAL LETTER H, LATIN SMALL LETTER H +test(0x0049, 0x0069); // LATIN CAPITAL LETTER I, LATIN SMALL LETTER I +test(0x004A, 0x006A); // LATIN CAPITAL LETTER J, LATIN SMALL LETTER J +test(0x004B, 0x006B, 0x212A); // LATIN CAPITAL LETTER K, LATIN SMALL LETTER K, KELVIN SIGN (DEGREES KELVIN) +test(0x004C, 0x006C); // LATIN CAPITAL LETTER L, LATIN SMALL LETTER L +test(0x004D, 0x006D); // LATIN CAPITAL LETTER M, LATIN SMALL LETTER M +test(0x004E, 0x006E); // LATIN CAPITAL LETTER N, LATIN SMALL LETTER N +test(0x004F, 0x006F); // LATIN CAPITAL LETTER O, LATIN SMALL LETTER O +test(0x0050, 0x0070); // LATIN CAPITAL LETTER P, LATIN SMALL LETTER P +test(0x0051, 0x0071); // LATIN CAPITAL LETTER Q, LATIN SMALL LETTER Q +test(0x0052, 0x0072); // LATIN CAPITAL LETTER R, LATIN SMALL LETTER R +test(0x0053, 0x0073, 0x017F); // LATIN CAPITAL LETTER S, LATIN SMALL LETTER S, LATIN SMALL LETTER LONG S +test(0x0054, 0x0074); // LATIN CAPITAL LETTER T, LATIN SMALL LETTER T +test(0x0055, 0x0075); // LATIN CAPITAL LETTER U, LATIN SMALL LETTER U +test(0x0056, 0x0076); // LATIN CAPITAL LETTER V, LATIN SMALL LETTER V +test(0x0057, 0x0077); // LATIN CAPITAL LETTER W, LATIN SMALL LETTER W +test(0x0058, 0x0078); // LATIN CAPITAL LETTER X, LATIN SMALL LETTER X +test(0x0059, 0x0079); // LATIN CAPITAL LETTER Y, LATIN SMALL LETTER Y +test(0x005A, 0x007A); // LATIN CAPITAL LETTER Z, LATIN SMALL LETTER Z +test(0x0061, 0x0041); // LATIN SMALL LETTER A, LATIN CAPITAL LETTER A +test(0x0062, 0x0042); // LATIN SMALL LETTER B, LATIN CAPITAL LETTER B +test(0x0063, 0x0043); // LATIN SMALL LETTER C, LATIN CAPITAL LETTER C +test(0x0064, 0x0044); // LATIN SMALL LETTER D, LATIN CAPITAL LETTER D +test(0x0065, 0x0045); // LATIN SMALL LETTER E, LATIN CAPITAL LETTER E +test(0x0066, 0x0046); // LATIN SMALL LETTER F, LATIN CAPITAL LETTER F +test(0x0067, 0x0047); // LATIN SMALL LETTER G, LATIN CAPITAL LETTER G +test(0x0068, 0x0048); // LATIN SMALL LETTER H, LATIN CAPITAL LETTER H +test(0x0069, 0x0049); // LATIN SMALL LETTER I, LATIN CAPITAL LETTER I +test(0x006A, 0x004A); // LATIN SMALL LETTER J, LATIN CAPITAL LETTER J +test(0x006B, 0x004B, 0x212A); // LATIN SMALL LETTER K, LATIN CAPITAL LETTER K, KELVIN SIGN (DEGREES KELVIN) +test(0x006C, 0x004C); // LATIN SMALL LETTER L, LATIN CAPITAL LETTER L +test(0x006D, 0x004D); // LATIN SMALL LETTER M, LATIN CAPITAL LETTER M +test(0x006E, 0x004E); // LATIN SMALL LETTER N, LATIN CAPITAL LETTER N +test(0x006F, 0x004F); // LATIN SMALL LETTER O, LATIN CAPITAL LETTER O +test(0x0070, 0x0050); // LATIN SMALL LETTER P, LATIN CAPITAL LETTER P +test(0x0071, 0x0051); // LATIN SMALL LETTER Q, LATIN CAPITAL LETTER Q +test(0x0072, 0x0052); // LATIN SMALL LETTER R, LATIN CAPITAL LETTER R +test(0x0073, 0x0053, 0x017F); // LATIN SMALL LETTER S, LATIN CAPITAL LETTER S, LATIN SMALL LETTER LONG S +test(0x0074, 0x0054); // LATIN SMALL LETTER T, LATIN CAPITAL LETTER T +test(0x0075, 0x0055); // LATIN SMALL LETTER U, LATIN CAPITAL LETTER U +test(0x0076, 0x0056); // LATIN SMALL LETTER V, LATIN CAPITAL LETTER V +test(0x0077, 0x0057); // LATIN SMALL LETTER W, LATIN CAPITAL LETTER W +test(0x0078, 0x0058); // LATIN SMALL LETTER X, LATIN CAPITAL LETTER X +test(0x0079, 0x0059); // LATIN SMALL LETTER Y, LATIN CAPITAL LETTER Y +test(0x007A, 0x005A); // LATIN SMALL LETTER Z, LATIN CAPITAL LETTER Z +test(0x00B5, 0x03BC, 0x039C); // MICRO SIGN, GREEK SMALL LETTER MU, GREEK CAPITAL LETTER MU +test(0x00C0, 0x00E0); // LATIN CAPITAL LETTER A WITH GRAVE (LATIN CAPITAL LETTER A GRAVE), LATIN SMALL LETTER A WITH GRAVE (LATIN SMALL LETTER A GRAVE) +test(0x00C1, 0x00E1); // LATIN CAPITAL LETTER A WITH ACUTE (LATIN CAPITAL LETTER A ACUTE), LATIN SMALL LETTER A WITH ACUTE (LATIN SMALL LETTER A ACUTE) +test(0x00C2, 0x00E2); // LATIN CAPITAL LETTER A WITH CIRCUMFLEX (LATIN CAPITAL LETTER A CIRCUMFLEX), LATIN SMALL LETTER A WITH CIRCUMFLEX (LATIN SMALL LETTER A CIRCUMFLEX) +test(0x00C3, 0x00E3); // LATIN CAPITAL LETTER A WITH TILDE (LATIN CAPITAL LETTER A TILDE), LATIN SMALL LETTER A WITH TILDE (LATIN SMALL LETTER A TILDE) +test(0x00C4, 0x00E4); // LATIN CAPITAL LETTER A WITH DIAERESIS (LATIN CAPITAL LETTER A DIAERESIS), LATIN SMALL LETTER A WITH DIAERESIS (LATIN SMALL LETTER A DIAERESIS) +test(0x00C5, 0x00E5, 0x212B); // LATIN CAPITAL LETTER A WITH RING ABOVE (LATIN CAPITAL LETTER A RING), LATIN SMALL LETTER A WITH RING ABOVE (LATIN SMALL LETTER A RING), ANGSTROM SIGN (ANGSTROM UNIT) +test(0x00C6, 0x00E6); // LATIN CAPITAL LETTER AE (LATIN CAPITAL LETTER A E), LATIN SMALL LETTER AE (LATIN SMALL LETTER A E) +test(0x00C7, 0x00E7); // LATIN CAPITAL LETTER C WITH CEDILLA (LATIN CAPITAL LETTER C CEDILLA), LATIN SMALL LETTER C WITH CEDILLA (LATIN SMALL LETTER C CEDILLA) +test(0x00C8, 0x00E8); // LATIN CAPITAL LETTER E WITH GRAVE (LATIN CAPITAL LETTER E GRAVE), LATIN SMALL LETTER E WITH GRAVE (LATIN SMALL LETTER E GRAVE) +test(0x00C9, 0x00E9); // LATIN CAPITAL LETTER E WITH ACUTE (LATIN CAPITAL LETTER E ACUTE), LATIN SMALL LETTER E WITH ACUTE (LATIN SMALL LETTER E ACUTE) +test(0x00CA, 0x00EA); // LATIN CAPITAL LETTER E WITH CIRCUMFLEX (LATIN CAPITAL LETTER E CIRCUMFLEX), LATIN SMALL LETTER E WITH CIRCUMFLEX (LATIN SMALL LETTER E CIRCUMFLEX) +test(0x00CB, 0x00EB); // LATIN CAPITAL LETTER E WITH DIAERESIS (LATIN CAPITAL LETTER E DIAERESIS), LATIN SMALL LETTER E WITH DIAERESIS (LATIN SMALL LETTER E DIAERESIS) +test(0x00CC, 0x00EC); // LATIN CAPITAL LETTER I WITH GRAVE (LATIN CAPITAL LETTER I GRAVE), LATIN SMALL LETTER I WITH GRAVE (LATIN SMALL LETTER I GRAVE) +test(0x00CD, 0x00ED); // LATIN CAPITAL LETTER I WITH ACUTE (LATIN CAPITAL LETTER I ACUTE), LATIN SMALL LETTER I WITH ACUTE (LATIN SMALL LETTER I ACUTE) +test(0x00CE, 0x00EE); // LATIN CAPITAL LETTER I WITH CIRCUMFLEX (LATIN CAPITAL LETTER I CIRCUMFLEX), LATIN SMALL LETTER I WITH CIRCUMFLEX (LATIN SMALL LETTER I CIRCUMFLEX) +test(0x00CF, 0x00EF); // LATIN CAPITAL LETTER I WITH DIAERESIS (LATIN CAPITAL LETTER I DIAERESIS), LATIN SMALL LETTER I WITH DIAERESIS (LATIN SMALL LETTER I DIAERESIS) +test(0x00D0, 0x00F0); // LATIN CAPITAL LETTER ETH, LATIN SMALL LETTER ETH +test(0x00D1, 0x00F1); // LATIN CAPITAL LETTER N WITH TILDE (LATIN CAPITAL LETTER N TILDE), LATIN SMALL LETTER N WITH TILDE (LATIN SMALL LETTER N TILDE) +test(0x00D2, 0x00F2); // LATIN CAPITAL LETTER O WITH GRAVE (LATIN CAPITAL LETTER O GRAVE), LATIN SMALL LETTER O WITH GRAVE (LATIN SMALL LETTER O GRAVE) +test(0x00D3, 0x00F3); // LATIN CAPITAL LETTER O WITH ACUTE (LATIN CAPITAL LETTER O ACUTE), LATIN SMALL LETTER O WITH ACUTE (LATIN SMALL LETTER O ACUTE) +test(0x00D4, 0x00F4); // LATIN CAPITAL LETTER O WITH CIRCUMFLEX (LATIN CAPITAL LETTER O CIRCUMFLEX), LATIN SMALL LETTER O WITH CIRCUMFLEX (LATIN SMALL LETTER O CIRCUMFLEX) +test(0x00D5, 0x00F5); // LATIN CAPITAL LETTER O WITH TILDE (LATIN CAPITAL LETTER O TILDE), LATIN SMALL LETTER O WITH TILDE (LATIN SMALL LETTER O TILDE) +test(0x00D6, 0x00F6); // LATIN CAPITAL LETTER O WITH DIAERESIS (LATIN CAPITAL LETTER O DIAERESIS), LATIN SMALL LETTER O WITH DIAERESIS (LATIN SMALL LETTER O DIAERESIS) +test(0x00D8, 0x00F8); // LATIN CAPITAL LETTER O WITH STROKE (LATIN CAPITAL LETTER O SLASH), LATIN SMALL LETTER O WITH STROKE (LATIN SMALL LETTER O SLASH) +test(0x00D9, 0x00F9); // LATIN CAPITAL LETTER U WITH GRAVE (LATIN CAPITAL LETTER U GRAVE), LATIN SMALL LETTER U WITH GRAVE (LATIN SMALL LETTER U GRAVE) +test(0x00DA, 0x00FA); // LATIN CAPITAL LETTER U WITH ACUTE (LATIN CAPITAL LETTER U ACUTE), LATIN SMALL LETTER U WITH ACUTE (LATIN SMALL LETTER U ACUTE) +test(0x00DB, 0x00FB); // LATIN CAPITAL LETTER U WITH CIRCUMFLEX (LATIN CAPITAL LETTER U CIRCUMFLEX), LATIN SMALL LETTER U WITH CIRCUMFLEX (LATIN SMALL LETTER U CIRCUMFLEX) +test(0x00DC, 0x00FC); // LATIN CAPITAL LETTER U WITH DIAERESIS (LATIN CAPITAL LETTER U DIAERESIS), LATIN SMALL LETTER U WITH DIAERESIS (LATIN SMALL LETTER U DIAERESIS) +test(0x00DD, 0x00FD); // LATIN CAPITAL LETTER Y WITH ACUTE (LATIN CAPITAL LETTER Y ACUTE), LATIN SMALL LETTER Y WITH ACUTE (LATIN SMALL LETTER Y ACUTE) +test(0x00DE, 0x00FE); // LATIN CAPITAL LETTER THORN, LATIN SMALL LETTER THORN +test(0x00DF, 0x1E9E); // LATIN SMALL LETTER SHARP S, LATIN CAPITAL LETTER SHARP S +test(0x00E0, 0x00C0); // LATIN SMALL LETTER A WITH GRAVE (LATIN SMALL LETTER A GRAVE), LATIN CAPITAL LETTER A WITH GRAVE (LATIN CAPITAL LETTER A GRAVE) +test(0x00E1, 0x00C1); // LATIN SMALL LETTER A WITH ACUTE (LATIN SMALL LETTER A ACUTE), LATIN CAPITAL LETTER A WITH ACUTE (LATIN CAPITAL LETTER A ACUTE) +test(0x00E2, 0x00C2); // LATIN SMALL LETTER A WITH CIRCUMFLEX (LATIN SMALL LETTER A CIRCUMFLEX), LATIN CAPITAL LETTER A WITH CIRCUMFLEX (LATIN CAPITAL LETTER A CIRCUMFLEX) +test(0x00E3, 0x00C3); // LATIN SMALL LETTER A WITH TILDE (LATIN SMALL LETTER A TILDE), LATIN CAPITAL LETTER A WITH TILDE (LATIN CAPITAL LETTER A TILDE) +test(0x00E4, 0x00C4); // LATIN SMALL LETTER A WITH DIAERESIS (LATIN SMALL LETTER A DIAERESIS), LATIN CAPITAL LETTER A WITH DIAERESIS (LATIN CAPITAL LETTER A DIAERESIS) +test(0x00E5, 0x00C5, 0x212B); // LATIN SMALL LETTER A WITH RING ABOVE (LATIN SMALL LETTER A RING), LATIN CAPITAL LETTER A WITH RING ABOVE (LATIN CAPITAL LETTER A RING), ANGSTROM SIGN (ANGSTROM UNIT) +test(0x00E6, 0x00C6); // LATIN SMALL LETTER AE (LATIN SMALL LETTER A E), LATIN CAPITAL LETTER AE (LATIN CAPITAL LETTER A E) +test(0x00E7, 0x00C7); // LATIN SMALL LETTER C WITH CEDILLA (LATIN SMALL LETTER C CEDILLA), LATIN CAPITAL LETTER C WITH CEDILLA (LATIN CAPITAL LETTER C CEDILLA) +test(0x00E8, 0x00C8); // LATIN SMALL LETTER E WITH GRAVE (LATIN SMALL LETTER E GRAVE), LATIN CAPITAL LETTER E WITH GRAVE (LATIN CAPITAL LETTER E GRAVE) +test(0x00E9, 0x00C9); // LATIN SMALL LETTER E WITH ACUTE (LATIN SMALL LETTER E ACUTE), LATIN CAPITAL LETTER E WITH ACUTE (LATIN CAPITAL LETTER E ACUTE) +test(0x00EA, 0x00CA); // LATIN SMALL LETTER E WITH CIRCUMFLEX (LATIN SMALL LETTER E CIRCUMFLEX), LATIN CAPITAL LETTER E WITH CIRCUMFLEX (LATIN CAPITAL LETTER E CIRCUMFLEX) +test(0x00EB, 0x00CB); // LATIN SMALL LETTER E WITH DIAERESIS (LATIN SMALL LETTER E DIAERESIS), LATIN CAPITAL LETTER E WITH DIAERESIS (LATIN CAPITAL LETTER E DIAERESIS) +test(0x00EC, 0x00CC); // LATIN SMALL LETTER I WITH GRAVE (LATIN SMALL LETTER I GRAVE), LATIN CAPITAL LETTER I WITH GRAVE (LATIN CAPITAL LETTER I GRAVE) +test(0x00ED, 0x00CD); // LATIN SMALL LETTER I WITH ACUTE (LATIN SMALL LETTER I ACUTE), LATIN CAPITAL LETTER I WITH ACUTE (LATIN CAPITAL LETTER I ACUTE) +test(0x00EE, 0x00CE); // LATIN SMALL LETTER I WITH CIRCUMFLEX (LATIN SMALL LETTER I CIRCUMFLEX), LATIN CAPITAL LETTER I WITH CIRCUMFLEX (LATIN CAPITAL LETTER I CIRCUMFLEX) +test(0x00EF, 0x00CF); // LATIN SMALL LETTER I WITH DIAERESIS (LATIN SMALL LETTER I DIAERESIS), LATIN CAPITAL LETTER I WITH DIAERESIS (LATIN CAPITAL LETTER I DIAERESIS) +test(0x00F0, 0x00D0); // LATIN SMALL LETTER ETH, LATIN CAPITAL LETTER ETH +test(0x00F1, 0x00D1); // LATIN SMALL LETTER N WITH TILDE (LATIN SMALL LETTER N TILDE), LATIN CAPITAL LETTER N WITH TILDE (LATIN CAPITAL LETTER N TILDE) +test(0x00F2, 0x00D2); // LATIN SMALL LETTER O WITH GRAVE (LATIN SMALL LETTER O GRAVE), LATIN CAPITAL LETTER O WITH GRAVE (LATIN CAPITAL LETTER O GRAVE) +test(0x00F3, 0x00D3); // LATIN SMALL LETTER O WITH ACUTE (LATIN SMALL LETTER O ACUTE), LATIN CAPITAL LETTER O WITH ACUTE (LATIN CAPITAL LETTER O ACUTE) +test(0x00F4, 0x00D4); // LATIN SMALL LETTER O WITH CIRCUMFLEX (LATIN SMALL LETTER O CIRCUMFLEX), LATIN CAPITAL LETTER O WITH CIRCUMFLEX (LATIN CAPITAL LETTER O CIRCUMFLEX) +test(0x00F5, 0x00D5); // LATIN SMALL LETTER O WITH TILDE (LATIN SMALL LETTER O TILDE), LATIN CAPITAL LETTER O WITH TILDE (LATIN CAPITAL LETTER O TILDE) +test(0x00F6, 0x00D6); // LATIN SMALL LETTER O WITH DIAERESIS (LATIN SMALL LETTER O DIAERESIS), LATIN CAPITAL LETTER O WITH DIAERESIS (LATIN CAPITAL LETTER O DIAERESIS) +test(0x00F8, 0x00D8); // LATIN SMALL LETTER O WITH STROKE (LATIN SMALL LETTER O SLASH), LATIN CAPITAL LETTER O WITH STROKE (LATIN CAPITAL LETTER O SLASH) +test(0x00F9, 0x00D9); // LATIN SMALL LETTER U WITH GRAVE (LATIN SMALL LETTER U GRAVE), LATIN CAPITAL LETTER U WITH GRAVE (LATIN CAPITAL LETTER U GRAVE) +test(0x00FA, 0x00DA); // LATIN SMALL LETTER U WITH ACUTE (LATIN SMALL LETTER U ACUTE), LATIN CAPITAL LETTER U WITH ACUTE (LATIN CAPITAL LETTER U ACUTE) +test(0x00FB, 0x00DB); // LATIN SMALL LETTER U WITH CIRCUMFLEX (LATIN SMALL LETTER U CIRCUMFLEX), LATIN CAPITAL LETTER U WITH CIRCUMFLEX (LATIN CAPITAL LETTER U CIRCUMFLEX) +test(0x00FC, 0x00DC); // LATIN SMALL LETTER U WITH DIAERESIS (LATIN SMALL LETTER U DIAERESIS), LATIN CAPITAL LETTER U WITH DIAERESIS (LATIN CAPITAL LETTER U DIAERESIS) +test(0x00FD, 0x00DD); // LATIN SMALL LETTER Y WITH ACUTE (LATIN SMALL LETTER Y ACUTE), LATIN CAPITAL LETTER Y WITH ACUTE (LATIN CAPITAL LETTER Y ACUTE) +test(0x00FE, 0x00DE); // LATIN SMALL LETTER THORN, LATIN CAPITAL LETTER THORN +test(0x00FF, 0x0178); // LATIN SMALL LETTER Y WITH DIAERESIS (LATIN SMALL LETTER Y DIAERESIS), LATIN CAPITAL LETTER Y WITH DIAERESIS (LATIN CAPITAL LETTER Y DIAERESIS) +test(0x0100, 0x0101); // LATIN CAPITAL LETTER A WITH MACRON (LATIN CAPITAL LETTER A MACRON), LATIN SMALL LETTER A WITH MACRON (LATIN SMALL LETTER A MACRON) +test(0x0101, 0x0100); // LATIN SMALL LETTER A WITH MACRON (LATIN SMALL LETTER A MACRON), LATIN CAPITAL LETTER A WITH MACRON (LATIN CAPITAL LETTER A MACRON) +test(0x0102, 0x0103); // LATIN CAPITAL LETTER A WITH BREVE (LATIN CAPITAL LETTER A BREVE), LATIN SMALL LETTER A WITH BREVE (LATIN SMALL LETTER A BREVE) +test(0x0103, 0x0102); // LATIN SMALL LETTER A WITH BREVE (LATIN SMALL LETTER A BREVE), LATIN CAPITAL LETTER A WITH BREVE (LATIN CAPITAL LETTER A BREVE) +test(0x0104, 0x0105); // LATIN CAPITAL LETTER A WITH OGONEK (LATIN CAPITAL LETTER A OGONEK), LATIN SMALL LETTER A WITH OGONEK (LATIN SMALL LETTER A OGONEK) +test(0x0105, 0x0104); // LATIN SMALL LETTER A WITH OGONEK (LATIN SMALL LETTER A OGONEK), LATIN CAPITAL LETTER A WITH OGONEK (LATIN CAPITAL LETTER A OGONEK) +test(0x0106, 0x0107); // LATIN CAPITAL LETTER C WITH ACUTE (LATIN CAPITAL LETTER C ACUTE), LATIN SMALL LETTER C WITH ACUTE (LATIN SMALL LETTER C ACUTE) +test(0x0107, 0x0106); // LATIN SMALL LETTER C WITH ACUTE (LATIN SMALL LETTER C ACUTE), LATIN CAPITAL LETTER C WITH ACUTE (LATIN CAPITAL LETTER C ACUTE) +test(0x0108, 0x0109); // LATIN CAPITAL LETTER C WITH CIRCUMFLEX (LATIN CAPITAL LETTER C CIRCUMFLEX), LATIN SMALL LETTER C WITH CIRCUMFLEX (LATIN SMALL LETTER C CIRCUMFLEX) +test(0x0109, 0x0108); // LATIN SMALL LETTER C WITH CIRCUMFLEX (LATIN SMALL LETTER C CIRCUMFLEX), LATIN CAPITAL LETTER C WITH CIRCUMFLEX (LATIN CAPITAL LETTER C CIRCUMFLEX) +test(0x010A, 0x010B); // LATIN CAPITAL LETTER C WITH DOT ABOVE (LATIN CAPITAL LETTER C DOT), LATIN SMALL LETTER C WITH DOT ABOVE (LATIN SMALL LETTER C DOT) +test(0x010B, 0x010A); // LATIN SMALL LETTER C WITH DOT ABOVE (LATIN SMALL LETTER C DOT), LATIN CAPITAL LETTER C WITH DOT ABOVE (LATIN CAPITAL LETTER C DOT) +test(0x010C, 0x010D); // LATIN CAPITAL LETTER C WITH CARON (LATIN CAPITAL LETTER C HACEK), LATIN SMALL LETTER C WITH CARON (LATIN SMALL LETTER C HACEK) +test(0x010D, 0x010C); // LATIN SMALL LETTER C WITH CARON (LATIN SMALL LETTER C HACEK), LATIN CAPITAL LETTER C WITH CARON (LATIN CAPITAL LETTER C HACEK) +test(0x010E, 0x010F); // LATIN CAPITAL LETTER D WITH CARON (LATIN CAPITAL LETTER D HACEK), LATIN SMALL LETTER D WITH CARON (LATIN SMALL LETTER D HACEK) +test(0x010F, 0x010E); // LATIN SMALL LETTER D WITH CARON (LATIN SMALL LETTER D HACEK), LATIN CAPITAL LETTER D WITH CARON (LATIN CAPITAL LETTER D HACEK) +test(0x0110, 0x0111); // LATIN CAPITAL LETTER D WITH STROKE (LATIN CAPITAL LETTER D BAR), LATIN SMALL LETTER D WITH STROKE (LATIN SMALL LETTER D BAR) +test(0x0111, 0x0110); // LATIN SMALL LETTER D WITH STROKE (LATIN SMALL LETTER D BAR), LATIN CAPITAL LETTER D WITH STROKE (LATIN CAPITAL LETTER D BAR) +test(0x0112, 0x0113); // LATIN CAPITAL LETTER E WITH MACRON (LATIN CAPITAL LETTER E MACRON), LATIN SMALL LETTER E WITH MACRON (LATIN SMALL LETTER E MACRON) +test(0x0113, 0x0112); // LATIN SMALL LETTER E WITH MACRON (LATIN SMALL LETTER E MACRON), LATIN CAPITAL LETTER E WITH MACRON (LATIN CAPITAL LETTER E MACRON) +test(0x0114, 0x0115); // LATIN CAPITAL LETTER E WITH BREVE (LATIN CAPITAL LETTER E BREVE), LATIN SMALL LETTER E WITH BREVE (LATIN SMALL LETTER E BREVE) +test(0x0115, 0x0114); // LATIN SMALL LETTER E WITH BREVE (LATIN SMALL LETTER E BREVE), LATIN CAPITAL LETTER E WITH BREVE (LATIN CAPITAL LETTER E BREVE) +test(0x0116, 0x0117); // LATIN CAPITAL LETTER E WITH DOT ABOVE (LATIN CAPITAL LETTER E DOT), LATIN SMALL LETTER E WITH DOT ABOVE (LATIN SMALL LETTER E DOT) +test(0x0117, 0x0116); // LATIN SMALL LETTER E WITH DOT ABOVE (LATIN SMALL LETTER E DOT), LATIN CAPITAL LETTER E WITH DOT ABOVE (LATIN CAPITAL LETTER E DOT) +test(0x0118, 0x0119); // LATIN CAPITAL LETTER E WITH OGONEK (LATIN CAPITAL LETTER E OGONEK), LATIN SMALL LETTER E WITH OGONEK (LATIN SMALL LETTER E OGONEK) +test(0x0119, 0x0118); // LATIN SMALL LETTER E WITH OGONEK (LATIN SMALL LETTER E OGONEK), LATIN CAPITAL LETTER E WITH OGONEK (LATIN CAPITAL LETTER E OGONEK) +test(0x011A, 0x011B); // LATIN CAPITAL LETTER E WITH CARON (LATIN CAPITAL LETTER E HACEK), LATIN SMALL LETTER E WITH CARON (LATIN SMALL LETTER E HACEK) +test(0x011B, 0x011A); // LATIN SMALL LETTER E WITH CARON (LATIN SMALL LETTER E HACEK), LATIN CAPITAL LETTER E WITH CARON (LATIN CAPITAL LETTER E HACEK) +test(0x011C, 0x011D); // LATIN CAPITAL LETTER G WITH CIRCUMFLEX (LATIN CAPITAL LETTER G CIRCUMFLEX), LATIN SMALL LETTER G WITH CIRCUMFLEX (LATIN SMALL LETTER G CIRCUMFLEX) +test(0x011D, 0x011C); // LATIN SMALL LETTER G WITH CIRCUMFLEX (LATIN SMALL LETTER G CIRCUMFLEX), LATIN CAPITAL LETTER G WITH CIRCUMFLEX (LATIN CAPITAL LETTER G CIRCUMFLEX) +test(0x011E, 0x011F); // LATIN CAPITAL LETTER G WITH BREVE (LATIN CAPITAL LETTER G BREVE), LATIN SMALL LETTER G WITH BREVE (LATIN SMALL LETTER G BREVE) +test(0x011F, 0x011E); // LATIN SMALL LETTER G WITH BREVE (LATIN SMALL LETTER G BREVE), LATIN CAPITAL LETTER G WITH BREVE (LATIN CAPITAL LETTER G BREVE) +test(0x0120, 0x0121); // LATIN CAPITAL LETTER G WITH DOT ABOVE (LATIN CAPITAL LETTER G DOT), LATIN SMALL LETTER G WITH DOT ABOVE (LATIN SMALL LETTER G DOT) +test(0x0121, 0x0120); // LATIN SMALL LETTER G WITH DOT ABOVE (LATIN SMALL LETTER G DOT), LATIN CAPITAL LETTER G WITH DOT ABOVE (LATIN CAPITAL LETTER G DOT) +test(0x0122, 0x0123); // LATIN CAPITAL LETTER G WITH CEDILLA (LATIN CAPITAL LETTER G CEDILLA), LATIN SMALL LETTER G WITH CEDILLA (LATIN SMALL LETTER G CEDILLA) +test(0x0123, 0x0122); // LATIN SMALL LETTER G WITH CEDILLA (LATIN SMALL LETTER G CEDILLA), LATIN CAPITAL LETTER G WITH CEDILLA (LATIN CAPITAL LETTER G CEDILLA) +test(0x0124, 0x0125); // LATIN CAPITAL LETTER H WITH CIRCUMFLEX (LATIN CAPITAL LETTER H CIRCUMFLEX), LATIN SMALL LETTER H WITH CIRCUMFLEX (LATIN SMALL LETTER H CIRCUMFLEX) +test(0x0125, 0x0124); // LATIN SMALL LETTER H WITH CIRCUMFLEX (LATIN SMALL LETTER H CIRCUMFLEX), LATIN CAPITAL LETTER H WITH CIRCUMFLEX (LATIN CAPITAL LETTER H CIRCUMFLEX) +test(0x0126, 0x0127); // LATIN CAPITAL LETTER H WITH STROKE (LATIN CAPITAL LETTER H BAR), LATIN SMALL LETTER H WITH STROKE (LATIN SMALL LETTER H BAR) +test(0x0127, 0x0126); // LATIN SMALL LETTER H WITH STROKE (LATIN SMALL LETTER H BAR), LATIN CAPITAL LETTER H WITH STROKE (LATIN CAPITAL LETTER H BAR) +test(0x0128, 0x0129); // LATIN CAPITAL LETTER I WITH TILDE (LATIN CAPITAL LETTER I TILDE), LATIN SMALL LETTER I WITH TILDE (LATIN SMALL LETTER I TILDE) +test(0x0129, 0x0128); // LATIN SMALL LETTER I WITH TILDE (LATIN SMALL LETTER I TILDE), LATIN CAPITAL LETTER I WITH TILDE (LATIN CAPITAL LETTER I TILDE) +test(0x012A, 0x012B); // LATIN CAPITAL LETTER I WITH MACRON (LATIN CAPITAL LETTER I MACRON), LATIN SMALL LETTER I WITH MACRON (LATIN SMALL LETTER I MACRON) +test(0x012B, 0x012A); // LATIN SMALL LETTER I WITH MACRON (LATIN SMALL LETTER I MACRON), LATIN CAPITAL LETTER I WITH MACRON (LATIN CAPITAL LETTER I MACRON) +test(0x012C, 0x012D); // LATIN CAPITAL LETTER I WITH BREVE (LATIN CAPITAL LETTER I BREVE), LATIN SMALL LETTER I WITH BREVE (LATIN SMALL LETTER I BREVE) +test(0x012D, 0x012C); // LATIN SMALL LETTER I WITH BREVE (LATIN SMALL LETTER I BREVE), LATIN CAPITAL LETTER I WITH BREVE (LATIN CAPITAL LETTER I BREVE) +test(0x012E, 0x012F); // LATIN CAPITAL LETTER I WITH OGONEK (LATIN CAPITAL LETTER I OGONEK), LATIN SMALL LETTER I WITH OGONEK (LATIN SMALL LETTER I OGONEK) +test(0x012F, 0x012E); // LATIN SMALL LETTER I WITH OGONEK (LATIN SMALL LETTER I OGONEK), LATIN CAPITAL LETTER I WITH OGONEK (LATIN CAPITAL LETTER I OGONEK) +test(0x0132, 0x0133); // LATIN CAPITAL LIGATURE IJ (LATIN CAPITAL LETTER I J), LATIN SMALL LIGATURE IJ (LATIN SMALL LETTER I J) +test(0x0133, 0x0132); // LATIN SMALL LIGATURE IJ (LATIN SMALL LETTER I J), LATIN CAPITAL LIGATURE IJ (LATIN CAPITAL LETTER I J) +test(0x0134, 0x0135); // LATIN CAPITAL LETTER J WITH CIRCUMFLEX (LATIN CAPITAL LETTER J CIRCUMFLEX), LATIN SMALL LETTER J WITH CIRCUMFLEX (LATIN SMALL LETTER J CIRCUMFLEX) +test(0x0135, 0x0134); // LATIN SMALL LETTER J WITH CIRCUMFLEX (LATIN SMALL LETTER J CIRCUMFLEX), LATIN CAPITAL LETTER J WITH CIRCUMFLEX (LATIN CAPITAL LETTER J CIRCUMFLEX) +test(0x0136, 0x0137); // LATIN CAPITAL LETTER K WITH CEDILLA (LATIN CAPITAL LETTER K CEDILLA), LATIN SMALL LETTER K WITH CEDILLA (LATIN SMALL LETTER K CEDILLA) +test(0x0137, 0x0136); // LATIN SMALL LETTER K WITH CEDILLA (LATIN SMALL LETTER K CEDILLA), LATIN CAPITAL LETTER K WITH CEDILLA (LATIN CAPITAL LETTER K CEDILLA) +test(0x0139, 0x013A); // LATIN CAPITAL LETTER L WITH ACUTE (LATIN CAPITAL LETTER L ACUTE), LATIN SMALL LETTER L WITH ACUTE (LATIN SMALL LETTER L ACUTE) +test(0x013A, 0x0139); // LATIN SMALL LETTER L WITH ACUTE (LATIN SMALL LETTER L ACUTE), LATIN CAPITAL LETTER L WITH ACUTE (LATIN CAPITAL LETTER L ACUTE) +test(0x013B, 0x013C); // LATIN CAPITAL LETTER L WITH CEDILLA (LATIN CAPITAL LETTER L CEDILLA), LATIN SMALL LETTER L WITH CEDILLA (LATIN SMALL LETTER L CEDILLA) +test(0x013C, 0x013B); // LATIN SMALL LETTER L WITH CEDILLA (LATIN SMALL LETTER L CEDILLA), LATIN CAPITAL LETTER L WITH CEDILLA (LATIN CAPITAL LETTER L CEDILLA) +test(0x013D, 0x013E); // LATIN CAPITAL LETTER L WITH CARON (LATIN CAPITAL LETTER L HACEK), LATIN SMALL LETTER L WITH CARON (LATIN SMALL LETTER L HACEK) +test(0x013E, 0x013D); // LATIN SMALL LETTER L WITH CARON (LATIN SMALL LETTER L HACEK), LATIN CAPITAL LETTER L WITH CARON (LATIN CAPITAL LETTER L HACEK) +test(0x013F, 0x0140); // LATIN CAPITAL LETTER L WITH MIDDLE DOT, LATIN SMALL LETTER L WITH MIDDLE DOT +test(0x0140, 0x013F); // LATIN SMALL LETTER L WITH MIDDLE DOT, LATIN CAPITAL LETTER L WITH MIDDLE DOT +test(0x0141, 0x0142); // LATIN CAPITAL LETTER L WITH STROKE (LATIN CAPITAL LETTER L SLASH), LATIN SMALL LETTER L WITH STROKE (LATIN SMALL LETTER L SLASH) +test(0x0142, 0x0141); // LATIN SMALL LETTER L WITH STROKE (LATIN SMALL LETTER L SLASH), LATIN CAPITAL LETTER L WITH STROKE (LATIN CAPITAL LETTER L SLASH) +test(0x0143, 0x0144); // LATIN CAPITAL LETTER N WITH ACUTE (LATIN CAPITAL LETTER N ACUTE), LATIN SMALL LETTER N WITH ACUTE (LATIN SMALL LETTER N ACUTE) +test(0x0144, 0x0143); // LATIN SMALL LETTER N WITH ACUTE (LATIN SMALL LETTER N ACUTE), LATIN CAPITAL LETTER N WITH ACUTE (LATIN CAPITAL LETTER N ACUTE) +test(0x0145, 0x0146); // LATIN CAPITAL LETTER N WITH CEDILLA (LATIN CAPITAL LETTER N CEDILLA), LATIN SMALL LETTER N WITH CEDILLA (LATIN SMALL LETTER N CEDILLA) +test(0x0146, 0x0145); // LATIN SMALL LETTER N WITH CEDILLA (LATIN SMALL LETTER N CEDILLA), LATIN CAPITAL LETTER N WITH CEDILLA (LATIN CAPITAL LETTER N CEDILLA) +test(0x0147, 0x0148); // LATIN CAPITAL LETTER N WITH CARON (LATIN CAPITAL LETTER N HACEK), LATIN SMALL LETTER N WITH CARON (LATIN SMALL LETTER N HACEK) +test(0x0148, 0x0147); // LATIN SMALL LETTER N WITH CARON (LATIN SMALL LETTER N HACEK), LATIN CAPITAL LETTER N WITH CARON (LATIN CAPITAL LETTER N HACEK) +test(0x014A, 0x014B); // LATIN CAPITAL LETTER ENG, LATIN SMALL LETTER ENG +test(0x014B, 0x014A); // LATIN SMALL LETTER ENG, LATIN CAPITAL LETTER ENG +test(0x014C, 0x014D); // LATIN CAPITAL LETTER O WITH MACRON (LATIN CAPITAL LETTER O MACRON), LATIN SMALL LETTER O WITH MACRON (LATIN SMALL LETTER O MACRON) +test(0x014D, 0x014C); // LATIN SMALL LETTER O WITH MACRON (LATIN SMALL LETTER O MACRON), LATIN CAPITAL LETTER O WITH MACRON (LATIN CAPITAL LETTER O MACRON) +test(0x014E, 0x014F); // LATIN CAPITAL LETTER O WITH BREVE (LATIN CAPITAL LETTER O BREVE), LATIN SMALL LETTER O WITH BREVE (LATIN SMALL LETTER O BREVE) +test(0x014F, 0x014E); // LATIN SMALL LETTER O WITH BREVE (LATIN SMALL LETTER O BREVE), LATIN CAPITAL LETTER O WITH BREVE (LATIN CAPITAL LETTER O BREVE) +test(0x0150, 0x0151); // LATIN CAPITAL LETTER O WITH DOUBLE ACUTE (LATIN CAPITAL LETTER O DOUBLE ACUTE), LATIN SMALL LETTER O WITH DOUBLE ACUTE (LATIN SMALL LETTER O DOUBLE ACUTE) +test(0x0151, 0x0150); // LATIN SMALL LETTER O WITH DOUBLE ACUTE (LATIN SMALL LETTER O DOUBLE ACUTE), LATIN CAPITAL LETTER O WITH DOUBLE ACUTE (LATIN CAPITAL LETTER O DOUBLE ACUTE) +test(0x0152, 0x0153); // LATIN CAPITAL LIGATURE OE (LATIN CAPITAL LETTER O E), LATIN SMALL LIGATURE OE (LATIN SMALL LETTER O E) +test(0x0153, 0x0152); // LATIN SMALL LIGATURE OE (LATIN SMALL LETTER O E), LATIN CAPITAL LIGATURE OE (LATIN CAPITAL LETTER O E) +test(0x0154, 0x0155); // LATIN CAPITAL LETTER R WITH ACUTE (LATIN CAPITAL LETTER R ACUTE), LATIN SMALL LETTER R WITH ACUTE (LATIN SMALL LETTER R ACUTE) +test(0x0155, 0x0154); // LATIN SMALL LETTER R WITH ACUTE (LATIN SMALL LETTER R ACUTE), LATIN CAPITAL LETTER R WITH ACUTE (LATIN CAPITAL LETTER R ACUTE) +test(0x0156, 0x0157); // LATIN CAPITAL LETTER R WITH CEDILLA (LATIN CAPITAL LETTER R CEDILLA), LATIN SMALL LETTER R WITH CEDILLA (LATIN SMALL LETTER R CEDILLA) +test(0x0157, 0x0156); // LATIN SMALL LETTER R WITH CEDILLA (LATIN SMALL LETTER R CEDILLA), LATIN CAPITAL LETTER R WITH CEDILLA (LATIN CAPITAL LETTER R CEDILLA) +test(0x0158, 0x0159); // LATIN CAPITAL LETTER R WITH CARON (LATIN CAPITAL LETTER R HACEK), LATIN SMALL LETTER R WITH CARON (LATIN SMALL LETTER R HACEK) +test(0x0159, 0x0158); // LATIN SMALL LETTER R WITH CARON (LATIN SMALL LETTER R HACEK), LATIN CAPITAL LETTER R WITH CARON (LATIN CAPITAL LETTER R HACEK) +test(0x015A, 0x015B); // LATIN CAPITAL LETTER S WITH ACUTE (LATIN CAPITAL LETTER S ACUTE), LATIN SMALL LETTER S WITH ACUTE (LATIN SMALL LETTER S ACUTE) +test(0x015B, 0x015A); // LATIN SMALL LETTER S WITH ACUTE (LATIN SMALL LETTER S ACUTE), LATIN CAPITAL LETTER S WITH ACUTE (LATIN CAPITAL LETTER S ACUTE) +test(0x015C, 0x015D); // LATIN CAPITAL LETTER S WITH CIRCUMFLEX (LATIN CAPITAL LETTER S CIRCUMFLEX), LATIN SMALL LETTER S WITH CIRCUMFLEX (LATIN SMALL LETTER S CIRCUMFLEX) +test(0x015D, 0x015C); // LATIN SMALL LETTER S WITH CIRCUMFLEX (LATIN SMALL LETTER S CIRCUMFLEX), LATIN CAPITAL LETTER S WITH CIRCUMFLEX (LATIN CAPITAL LETTER S CIRCUMFLEX) +test(0x015E, 0x015F); // LATIN CAPITAL LETTER S WITH CEDILLA (LATIN CAPITAL LETTER S CEDILLA), LATIN SMALL LETTER S WITH CEDILLA (LATIN SMALL LETTER S CEDILLA) +test(0x015F, 0x015E); // LATIN SMALL LETTER S WITH CEDILLA (LATIN SMALL LETTER S CEDILLA), LATIN CAPITAL LETTER S WITH CEDILLA (LATIN CAPITAL LETTER S CEDILLA) +test(0x0160, 0x0161); // LATIN CAPITAL LETTER S WITH CARON (LATIN CAPITAL LETTER S HACEK), LATIN SMALL LETTER S WITH CARON (LATIN SMALL LETTER S HACEK) +test(0x0161, 0x0160); // LATIN SMALL LETTER S WITH CARON (LATIN SMALL LETTER S HACEK), LATIN CAPITAL LETTER S WITH CARON (LATIN CAPITAL LETTER S HACEK) +test(0x0162, 0x0163); // LATIN CAPITAL LETTER T WITH CEDILLA (LATIN CAPITAL LETTER T CEDILLA), LATIN SMALL LETTER T WITH CEDILLA (LATIN SMALL LETTER T CEDILLA) +test(0x0163, 0x0162); // LATIN SMALL LETTER T WITH CEDILLA (LATIN SMALL LETTER T CEDILLA), LATIN CAPITAL LETTER T WITH CEDILLA (LATIN CAPITAL LETTER T CEDILLA) +test(0x0164, 0x0165); // LATIN CAPITAL LETTER T WITH CARON (LATIN CAPITAL LETTER T HACEK), LATIN SMALL LETTER T WITH CARON (LATIN SMALL LETTER T HACEK) +test(0x0165, 0x0164); // LATIN SMALL LETTER T WITH CARON (LATIN SMALL LETTER T HACEK), LATIN CAPITAL LETTER T WITH CARON (LATIN CAPITAL LETTER T HACEK) +test(0x0166, 0x0167); // LATIN CAPITAL LETTER T WITH STROKE (LATIN CAPITAL LETTER T BAR), LATIN SMALL LETTER T WITH STROKE (LATIN SMALL LETTER T BAR) +test(0x0167, 0x0166); // LATIN SMALL LETTER T WITH STROKE (LATIN SMALL LETTER T BAR), LATIN CAPITAL LETTER T WITH STROKE (LATIN CAPITAL LETTER T BAR) +test(0x0168, 0x0169); // LATIN CAPITAL LETTER U WITH TILDE (LATIN CAPITAL LETTER U TILDE), LATIN SMALL LETTER U WITH TILDE (LATIN SMALL LETTER U TILDE) +test(0x0169, 0x0168); // LATIN SMALL LETTER U WITH TILDE (LATIN SMALL LETTER U TILDE), LATIN CAPITAL LETTER U WITH TILDE (LATIN CAPITAL LETTER U TILDE) +test(0x016A, 0x016B); // LATIN CAPITAL LETTER U WITH MACRON (LATIN CAPITAL LETTER U MACRON), LATIN SMALL LETTER U WITH MACRON (LATIN SMALL LETTER U MACRON) +test(0x016B, 0x016A); // LATIN SMALL LETTER U WITH MACRON (LATIN SMALL LETTER U MACRON), LATIN CAPITAL LETTER U WITH MACRON (LATIN CAPITAL LETTER U MACRON) +test(0x016C, 0x016D); // LATIN CAPITAL LETTER U WITH BREVE (LATIN CAPITAL LETTER U BREVE), LATIN SMALL LETTER U WITH BREVE (LATIN SMALL LETTER U BREVE) +test(0x016D, 0x016C); // LATIN SMALL LETTER U WITH BREVE (LATIN SMALL LETTER U BREVE), LATIN CAPITAL LETTER U WITH BREVE (LATIN CAPITAL LETTER U BREVE) +test(0x016E, 0x016F); // LATIN CAPITAL LETTER U WITH RING ABOVE (LATIN CAPITAL LETTER U RING), LATIN SMALL LETTER U WITH RING ABOVE (LATIN SMALL LETTER U RING) +test(0x016F, 0x016E); // LATIN SMALL LETTER U WITH RING ABOVE (LATIN SMALL LETTER U RING), LATIN CAPITAL LETTER U WITH RING ABOVE (LATIN CAPITAL LETTER U RING) +test(0x0170, 0x0171); // LATIN CAPITAL LETTER U WITH DOUBLE ACUTE (LATIN CAPITAL LETTER U DOUBLE ACUTE), LATIN SMALL LETTER U WITH DOUBLE ACUTE (LATIN SMALL LETTER U DOUBLE ACUTE) +test(0x0171, 0x0170); // LATIN SMALL LETTER U WITH DOUBLE ACUTE (LATIN SMALL LETTER U DOUBLE ACUTE), LATIN CAPITAL LETTER U WITH DOUBLE ACUTE (LATIN CAPITAL LETTER U DOUBLE ACUTE) +test(0x0172, 0x0173); // LATIN CAPITAL LETTER U WITH OGONEK (LATIN CAPITAL LETTER U OGONEK), LATIN SMALL LETTER U WITH OGONEK (LATIN SMALL LETTER U OGONEK) +test(0x0173, 0x0172); // LATIN SMALL LETTER U WITH OGONEK (LATIN SMALL LETTER U OGONEK), LATIN CAPITAL LETTER U WITH OGONEK (LATIN CAPITAL LETTER U OGONEK) +test(0x0174, 0x0175); // LATIN CAPITAL LETTER W WITH CIRCUMFLEX (LATIN CAPITAL LETTER W CIRCUMFLEX), LATIN SMALL LETTER W WITH CIRCUMFLEX (LATIN SMALL LETTER W CIRCUMFLEX) +test(0x0175, 0x0174); // LATIN SMALL LETTER W WITH CIRCUMFLEX (LATIN SMALL LETTER W CIRCUMFLEX), LATIN CAPITAL LETTER W WITH CIRCUMFLEX (LATIN CAPITAL LETTER W CIRCUMFLEX) +test(0x0176, 0x0177); // LATIN CAPITAL LETTER Y WITH CIRCUMFLEX (LATIN CAPITAL LETTER Y CIRCUMFLEX), LATIN SMALL LETTER Y WITH CIRCUMFLEX (LATIN SMALL LETTER Y CIRCUMFLEX) +test(0x0177, 0x0176); // LATIN SMALL LETTER Y WITH CIRCUMFLEX (LATIN SMALL LETTER Y CIRCUMFLEX), LATIN CAPITAL LETTER Y WITH CIRCUMFLEX (LATIN CAPITAL LETTER Y CIRCUMFLEX) +test(0x0178, 0x00FF); // LATIN CAPITAL LETTER Y WITH DIAERESIS (LATIN CAPITAL LETTER Y DIAERESIS), LATIN SMALL LETTER Y WITH DIAERESIS (LATIN SMALL LETTER Y DIAERESIS) +test(0x0179, 0x017A); // LATIN CAPITAL LETTER Z WITH ACUTE (LATIN CAPITAL LETTER Z ACUTE), LATIN SMALL LETTER Z WITH ACUTE (LATIN SMALL LETTER Z ACUTE) +test(0x017A, 0x0179); // LATIN SMALL LETTER Z WITH ACUTE (LATIN SMALL LETTER Z ACUTE), LATIN CAPITAL LETTER Z WITH ACUTE (LATIN CAPITAL LETTER Z ACUTE) +test(0x017B, 0x017C); // LATIN CAPITAL LETTER Z WITH DOT ABOVE (LATIN CAPITAL LETTER Z DOT), LATIN SMALL LETTER Z WITH DOT ABOVE (LATIN SMALL LETTER Z DOT) +test(0x017C, 0x017B); // LATIN SMALL LETTER Z WITH DOT ABOVE (LATIN SMALL LETTER Z DOT), LATIN CAPITAL LETTER Z WITH DOT ABOVE (LATIN CAPITAL LETTER Z DOT) +test(0x017D, 0x017E); // LATIN CAPITAL LETTER Z WITH CARON (LATIN CAPITAL LETTER Z HACEK), LATIN SMALL LETTER Z WITH CARON (LATIN SMALL LETTER Z HACEK) +test(0x017E, 0x017D); // LATIN SMALL LETTER Z WITH CARON (LATIN SMALL LETTER Z HACEK), LATIN CAPITAL LETTER Z WITH CARON (LATIN CAPITAL LETTER Z HACEK) +test(0x017F, 0x0073, 0x0053); // LATIN SMALL LETTER LONG S, LATIN SMALL LETTER S, LATIN CAPITAL LETTER S +test(0x0180, 0x0243); // LATIN SMALL LETTER B WITH STROKE (LATIN SMALL LETTER B BAR), LATIN CAPITAL LETTER B WITH STROKE +test(0x0181, 0x0253); // LATIN CAPITAL LETTER B WITH HOOK (LATIN CAPITAL LETTER B HOOK), LATIN SMALL LETTER B WITH HOOK (LATIN SMALL LETTER B HOOK) +test(0x0182, 0x0183); // LATIN CAPITAL LETTER B WITH TOPBAR (LATIN CAPITAL LETTER B TOPBAR), LATIN SMALL LETTER B WITH TOPBAR (LATIN SMALL LETTER B TOPBAR) +test(0x0183, 0x0182); // LATIN SMALL LETTER B WITH TOPBAR (LATIN SMALL LETTER B TOPBAR), LATIN CAPITAL LETTER B WITH TOPBAR (LATIN CAPITAL LETTER B TOPBAR) +test(0x0184, 0x0185); // LATIN CAPITAL LETTER TONE SIX, LATIN SMALL LETTER TONE SIX +test(0x0185, 0x0184); // LATIN SMALL LETTER TONE SIX, LATIN CAPITAL LETTER TONE SIX +test(0x0186, 0x0254); // LATIN CAPITAL LETTER OPEN O, LATIN SMALL LETTER OPEN O +test(0x0187, 0x0188); // LATIN CAPITAL LETTER C WITH HOOK (LATIN CAPITAL LETTER C HOOK), LATIN SMALL LETTER C WITH HOOK (LATIN SMALL LETTER C HOOK) +test(0x0188, 0x0187); // LATIN SMALL LETTER C WITH HOOK (LATIN SMALL LETTER C HOOK), LATIN CAPITAL LETTER C WITH HOOK (LATIN CAPITAL LETTER C HOOK) +test(0x0189, 0x0256); // LATIN CAPITAL LETTER AFRICAN D, LATIN SMALL LETTER D WITH TAIL (LATIN SMALL LETTER D RETROFLEX HOOK) +test(0x018A, 0x0257); // LATIN CAPITAL LETTER D WITH HOOK (LATIN CAPITAL LETTER D HOOK), LATIN SMALL LETTER D WITH HOOK (LATIN SMALL LETTER D HOOK) +test(0x018B, 0x018C); // LATIN CAPITAL LETTER D WITH TOPBAR (LATIN CAPITAL LETTER D TOPBAR), LATIN SMALL LETTER D WITH TOPBAR (LATIN SMALL LETTER D TOPBAR) +test(0x018C, 0x018B); // LATIN SMALL LETTER D WITH TOPBAR (LATIN SMALL LETTER D TOPBAR), LATIN CAPITAL LETTER D WITH TOPBAR (LATIN CAPITAL LETTER D TOPBAR) +test(0x018E, 0x01DD); // LATIN CAPITAL LETTER REVERSED E (LATIN CAPITAL LETTER TURNED E), LATIN SMALL LETTER TURNED E +test(0x018F, 0x0259); // LATIN CAPITAL LETTER SCHWA, LATIN SMALL LETTER SCHWA +test(0x0190, 0x025B); // LATIN CAPITAL LETTER OPEN E (LATIN CAPITAL LETTER EPSILON), LATIN SMALL LETTER OPEN E (LATIN SMALL LETTER EPSILON) +test(0x0191, 0x0192); // LATIN CAPITAL LETTER F WITH HOOK (LATIN CAPITAL LETTER F HOOK), LATIN SMALL LETTER F WITH HOOK (LATIN SMALL LETTER SCRIPT F) +test(0x0192, 0x0191); // LATIN SMALL LETTER F WITH HOOK (LATIN SMALL LETTER SCRIPT F), LATIN CAPITAL LETTER F WITH HOOK (LATIN CAPITAL LETTER F HOOK) +test(0x0193, 0x0260); // LATIN CAPITAL LETTER G WITH HOOK (LATIN CAPITAL LETTER G HOOK), LATIN SMALL LETTER G WITH HOOK (LATIN SMALL LETTER G HOOK) +test(0x0194, 0x0263); // LATIN CAPITAL LETTER GAMMA, LATIN SMALL LETTER GAMMA +test(0x0195, 0x01F6); // LATIN SMALL LETTER HV (LATIN SMALL LETTER H V), LATIN CAPITAL LETTER HWAIR +test(0x0196, 0x0269); // LATIN CAPITAL LETTER IOTA, LATIN SMALL LETTER IOTA +test(0x0197, 0x0268); // LATIN CAPITAL LETTER I WITH STROKE (LATIN CAPITAL LETTER BARRED I), LATIN SMALL LETTER I WITH STROKE (LATIN SMALL LETTER BARRED I) +test(0x0198, 0x0199); // LATIN CAPITAL LETTER K WITH HOOK (LATIN CAPITAL LETTER K HOOK), LATIN SMALL LETTER K WITH HOOK (LATIN SMALL LETTER K HOOK) +test(0x0199, 0x0198); // LATIN SMALL LETTER K WITH HOOK (LATIN SMALL LETTER K HOOK), LATIN CAPITAL LETTER K WITH HOOK (LATIN CAPITAL LETTER K HOOK) +test(0x019A, 0x023D); // LATIN SMALL LETTER L WITH BAR (LATIN SMALL LETTER BARRED L), LATIN CAPITAL LETTER L WITH BAR +test(0x019C, 0x026F); // LATIN CAPITAL LETTER TURNED M, LATIN SMALL LETTER TURNED M +test(0x019D, 0x0272); // LATIN CAPITAL LETTER N WITH LEFT HOOK (LATIN CAPITAL LETTER N HOOK), LATIN SMALL LETTER N WITH LEFT HOOK (LATIN SMALL LETTER N HOOK) +test(0x019E, 0x0220); // LATIN SMALL LETTER N WITH LONG RIGHT LEG, LATIN CAPITAL LETTER N WITH LONG RIGHT LEG +test(0x019F, 0x0275); // LATIN CAPITAL LETTER O WITH MIDDLE TILDE (LATIN CAPITAL LETTER BARRED O), LATIN SMALL LETTER BARRED O +test(0x01A0, 0x01A1); // LATIN CAPITAL LETTER O WITH HORN (LATIN CAPITAL LETTER O HORN), LATIN SMALL LETTER O WITH HORN (LATIN SMALL LETTER O HORN) +test(0x01A1, 0x01A0); // LATIN SMALL LETTER O WITH HORN (LATIN SMALL LETTER O HORN), LATIN CAPITAL LETTER O WITH HORN (LATIN CAPITAL LETTER O HORN) +test(0x01A2, 0x01A3); // LATIN CAPITAL LETTER OI (LATIN CAPITAL LETTER O I), LATIN SMALL LETTER OI (LATIN SMALL LETTER O I) +test(0x01A3, 0x01A2); // LATIN SMALL LETTER OI (LATIN SMALL LETTER O I), LATIN CAPITAL LETTER OI (LATIN CAPITAL LETTER O I) +test(0x01A4, 0x01A5); // LATIN CAPITAL LETTER P WITH HOOK (LATIN CAPITAL LETTER P HOOK), LATIN SMALL LETTER P WITH HOOK (LATIN SMALL LETTER P HOOK) +test(0x01A5, 0x01A4); // LATIN SMALL LETTER P WITH HOOK (LATIN SMALL LETTER P HOOK), LATIN CAPITAL LETTER P WITH HOOK (LATIN CAPITAL LETTER P HOOK) +test(0x01A6, 0x0280); // LATIN LETTER YR (LATIN LETTER Y R), LATIN LETTER SMALL CAPITAL R +test(0x01A7, 0x01A8); // LATIN CAPITAL LETTER TONE TWO, LATIN SMALL LETTER TONE TWO +test(0x01A8, 0x01A7); // LATIN SMALL LETTER TONE TWO, LATIN CAPITAL LETTER TONE TWO +test(0x01A9, 0x0283); // LATIN CAPITAL LETTER ESH, LATIN SMALL LETTER ESH +test(0x01AC, 0x01AD); // LATIN CAPITAL LETTER T WITH HOOK (LATIN CAPITAL LETTER T HOOK), LATIN SMALL LETTER T WITH HOOK (LATIN SMALL LETTER T HOOK) +test(0x01AD, 0x01AC); // LATIN SMALL LETTER T WITH HOOK (LATIN SMALL LETTER T HOOK), LATIN CAPITAL LETTER T WITH HOOK (LATIN CAPITAL LETTER T HOOK) +test(0x01AE, 0x0288); // LATIN CAPITAL LETTER T WITH RETROFLEX HOOK (LATIN CAPITAL LETTER T RETROFLEX HOOK), LATIN SMALL LETTER T WITH RETROFLEX HOOK (LATIN SMALL LETTER T RETROFLEX HOOK) +test(0x01AF, 0x01B0); // LATIN CAPITAL LETTER U WITH HORN (LATIN CAPITAL LETTER U HORN), LATIN SMALL LETTER U WITH HORN (LATIN SMALL LETTER U HORN) +test(0x01B0, 0x01AF); // LATIN SMALL LETTER U WITH HORN (LATIN SMALL LETTER U HORN), LATIN CAPITAL LETTER U WITH HORN (LATIN CAPITAL LETTER U HORN) +test(0x01B1, 0x028A); // LATIN CAPITAL LETTER UPSILON, LATIN SMALL LETTER UPSILON +test(0x01B2, 0x028B); // LATIN CAPITAL LETTER V WITH HOOK (LATIN CAPITAL LETTER SCRIPT V), LATIN SMALL LETTER V WITH HOOK (LATIN SMALL LETTER SCRIPT V) +test(0x01B3, 0x01B4); // LATIN CAPITAL LETTER Y WITH HOOK (LATIN CAPITAL LETTER Y HOOK), LATIN SMALL LETTER Y WITH HOOK (LATIN SMALL LETTER Y HOOK) +test(0x01B4, 0x01B3); // LATIN SMALL LETTER Y WITH HOOK (LATIN SMALL LETTER Y HOOK), LATIN CAPITAL LETTER Y WITH HOOK (LATIN CAPITAL LETTER Y HOOK) +test(0x01B5, 0x01B6); // LATIN CAPITAL LETTER Z WITH STROKE (LATIN CAPITAL LETTER Z BAR), LATIN SMALL LETTER Z WITH STROKE (LATIN SMALL LETTER Z BAR) +test(0x01B6, 0x01B5); // LATIN SMALL LETTER Z WITH STROKE (LATIN SMALL LETTER Z BAR), LATIN CAPITAL LETTER Z WITH STROKE (LATIN CAPITAL LETTER Z BAR) +test(0x01B7, 0x0292); // LATIN CAPITAL LETTER EZH (LATIN CAPITAL LETTER YOGH), LATIN SMALL LETTER EZH (LATIN SMALL LETTER YOGH) +test(0x01B8, 0x01B9); // LATIN CAPITAL LETTER EZH REVERSED (LATIN CAPITAL LETTER REVERSED YOGH), LATIN SMALL LETTER EZH REVERSED (LATIN SMALL LETTER REVERSED YOGH) +test(0x01B9, 0x01B8); // LATIN SMALL LETTER EZH REVERSED (LATIN SMALL LETTER REVERSED YOGH), LATIN CAPITAL LETTER EZH REVERSED (LATIN CAPITAL LETTER REVERSED YOGH) +test(0x01BC, 0x01BD); // LATIN CAPITAL LETTER TONE FIVE, LATIN SMALL LETTER TONE FIVE +test(0x01BD, 0x01BC); // LATIN SMALL LETTER TONE FIVE, LATIN CAPITAL LETTER TONE FIVE +test(0x01BF, 0x01F7); // LATIN LETTER WYNN, LATIN CAPITAL LETTER WYNN +test(0x01C4, 0x01C6, 0x01C5); // LATIN CAPITAL LETTER DZ WITH CARON (LATIN CAPITAL LETTER D Z HACEK), LATIN SMALL LETTER DZ WITH CARON (LATIN SMALL LETTER D Z HACEK), LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON (LATIN LETTER CAPITAL D SMALL Z HACEK) +test(0x01C5, 0x01C6, 0x01C4); // LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON (LATIN LETTER CAPITAL D SMALL Z HACEK), LATIN SMALL LETTER DZ WITH CARON (LATIN SMALL LETTER D Z HACEK), LATIN CAPITAL LETTER DZ WITH CARON (LATIN CAPITAL LETTER D Z HACEK) +test(0x01C6, 0x01C4, 0x01C5); // LATIN SMALL LETTER DZ WITH CARON (LATIN SMALL LETTER D Z HACEK), LATIN CAPITAL LETTER DZ WITH CARON (LATIN CAPITAL LETTER D Z HACEK), LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON (LATIN LETTER CAPITAL D SMALL Z HACEK) +test(0x01C7, 0x01C9, 0x01C8); // LATIN CAPITAL LETTER LJ (LATIN CAPITAL LETTER L J), LATIN SMALL LETTER LJ (LATIN SMALL LETTER L J), LATIN CAPITAL LETTER L WITH SMALL LETTER J (LATIN LETTER CAPITAL L SMALL J) +test(0x01C8, 0x01C9, 0x01C7); // LATIN CAPITAL LETTER L WITH SMALL LETTER J (LATIN LETTER CAPITAL L SMALL J), LATIN SMALL LETTER LJ (LATIN SMALL LETTER L J), LATIN CAPITAL LETTER LJ (LATIN CAPITAL LETTER L J) +test(0x01C9, 0x01C7, 0x01C8); // LATIN SMALL LETTER LJ (LATIN SMALL LETTER L J), LATIN CAPITAL LETTER LJ (LATIN CAPITAL LETTER L J), LATIN CAPITAL LETTER L WITH SMALL LETTER J (LATIN LETTER CAPITAL L SMALL J) +test(0x01CA, 0x01CC, 0x01CB); // LATIN CAPITAL LETTER NJ (LATIN CAPITAL LETTER N J), LATIN SMALL LETTER NJ (LATIN SMALL LETTER N J), LATIN CAPITAL LETTER N WITH SMALL LETTER J (LATIN LETTER CAPITAL N SMALL J) +test(0x01CB, 0x01CC, 0x01CA); // LATIN CAPITAL LETTER N WITH SMALL LETTER J (LATIN LETTER CAPITAL N SMALL J), LATIN SMALL LETTER NJ (LATIN SMALL LETTER N J), LATIN CAPITAL LETTER NJ (LATIN CAPITAL LETTER N J) +test(0x01CC, 0x01CA, 0x01CB); // LATIN SMALL LETTER NJ (LATIN SMALL LETTER N J), LATIN CAPITAL LETTER NJ (LATIN CAPITAL LETTER N J), LATIN CAPITAL LETTER N WITH SMALL LETTER J (LATIN LETTER CAPITAL N SMALL J) +test(0x01CD, 0x01CE); // LATIN CAPITAL LETTER A WITH CARON (LATIN CAPITAL LETTER A HACEK), LATIN SMALL LETTER A WITH CARON (LATIN SMALL LETTER A HACEK) +test(0x01CE, 0x01CD); // LATIN SMALL LETTER A WITH CARON (LATIN SMALL LETTER A HACEK), LATIN CAPITAL LETTER A WITH CARON (LATIN CAPITAL LETTER A HACEK) +test(0x01CF, 0x01D0); // LATIN CAPITAL LETTER I WITH CARON (LATIN CAPITAL LETTER I HACEK), LATIN SMALL LETTER I WITH CARON (LATIN SMALL LETTER I HACEK) +test(0x01D0, 0x01CF); // LATIN SMALL LETTER I WITH CARON (LATIN SMALL LETTER I HACEK), LATIN CAPITAL LETTER I WITH CARON (LATIN CAPITAL LETTER I HACEK) +test(0x01D1, 0x01D2); // LATIN CAPITAL LETTER O WITH CARON (LATIN CAPITAL LETTER O HACEK), LATIN SMALL LETTER O WITH CARON (LATIN SMALL LETTER O HACEK) +test(0x01D2, 0x01D1); // LATIN SMALL LETTER O WITH CARON (LATIN SMALL LETTER O HACEK), LATIN CAPITAL LETTER O WITH CARON (LATIN CAPITAL LETTER O HACEK) +test(0x01D3, 0x01D4); // LATIN CAPITAL LETTER U WITH CARON (LATIN CAPITAL LETTER U HACEK), LATIN SMALL LETTER U WITH CARON (LATIN SMALL LETTER U HACEK) +test(0x01D4, 0x01D3); // LATIN SMALL LETTER U WITH CARON (LATIN SMALL LETTER U HACEK), LATIN CAPITAL LETTER U WITH CARON (LATIN CAPITAL LETTER U HACEK) +test(0x01D5, 0x01D6); // LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON (LATIN CAPITAL LETTER U DIAERESIS MACRON), LATIN SMALL LETTER U WITH DIAERESIS AND MACRON (LATIN SMALL LETTER U DIAERESIS MACRON) +test(0x01D6, 0x01D5); // LATIN SMALL LETTER U WITH DIAERESIS AND MACRON (LATIN SMALL LETTER U DIAERESIS MACRON), LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON (LATIN CAPITAL LETTER U DIAERESIS MACRON) +test(0x01D7, 0x01D8); // LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE (LATIN CAPITAL LETTER U DIAERESIS ACUTE), LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE (LATIN SMALL LETTER U DIAERESIS ACUTE) +test(0x01D8, 0x01D7); // LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE (LATIN SMALL LETTER U DIAERESIS ACUTE), LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE (LATIN CAPITAL LETTER U DIAERESIS ACUTE) +test(0x01D9, 0x01DA); // LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON (LATIN CAPITAL LETTER U DIAERESIS HACEK), LATIN SMALL LETTER U WITH DIAERESIS AND CARON (LATIN SMALL LETTER U DIAERESIS HACEK) +test(0x01DA, 0x01D9); // LATIN SMALL LETTER U WITH DIAERESIS AND CARON (LATIN SMALL LETTER U DIAERESIS HACEK), LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON (LATIN CAPITAL LETTER U DIAERESIS HACEK) +test(0x01DB, 0x01DC); // LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE (LATIN CAPITAL LETTER U DIAERESIS GRAVE), LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE (LATIN SMALL LETTER U DIAERESIS GRAVE) +test(0x01DC, 0x01DB); // LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE (LATIN SMALL LETTER U DIAERESIS GRAVE), LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE (LATIN CAPITAL LETTER U DIAERESIS GRAVE) +test(0x01DD, 0x018E); // LATIN SMALL LETTER TURNED E, LATIN CAPITAL LETTER REVERSED E (LATIN CAPITAL LETTER TURNED E) +test(0x01DE, 0x01DF); // LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON (LATIN CAPITAL LETTER A DIAERESIS MACRON), LATIN SMALL LETTER A WITH DIAERESIS AND MACRON (LATIN SMALL LETTER A DIAERESIS MACRON) +test(0x01DF, 0x01DE); // LATIN SMALL LETTER A WITH DIAERESIS AND MACRON (LATIN SMALL LETTER A DIAERESIS MACRON), LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON (LATIN CAPITAL LETTER A DIAERESIS MACRON) +test(0x01E0, 0x01E1); // LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON (LATIN CAPITAL LETTER A DOT MACRON), LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON (LATIN SMALL LETTER A DOT MACRON) +test(0x01E1, 0x01E0); // LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON (LATIN SMALL LETTER A DOT MACRON), LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON (LATIN CAPITAL LETTER A DOT MACRON) +test(0x01E2, 0x01E3); // LATIN CAPITAL LETTER AE WITH MACRON (LATIN CAPITAL LETTER A E MACRON), LATIN SMALL LETTER AE WITH MACRON (LATIN SMALL LETTER A E MACRON) +test(0x01E3, 0x01E2); // LATIN SMALL LETTER AE WITH MACRON (LATIN SMALL LETTER A E MACRON), LATIN CAPITAL LETTER AE WITH MACRON (LATIN CAPITAL LETTER A E MACRON) +test(0x01E4, 0x01E5); // LATIN CAPITAL LETTER G WITH STROKE (LATIN CAPITAL LETTER G BAR), LATIN SMALL LETTER G WITH STROKE (LATIN SMALL LETTER G BAR) +test(0x01E5, 0x01E4); // LATIN SMALL LETTER G WITH STROKE (LATIN SMALL LETTER G BAR), LATIN CAPITAL LETTER G WITH STROKE (LATIN CAPITAL LETTER G BAR) +test(0x01E6, 0x01E7); // LATIN CAPITAL LETTER G WITH CARON (LATIN CAPITAL LETTER G HACEK), LATIN SMALL LETTER G WITH CARON (LATIN SMALL LETTER G HACEK) +test(0x01E7, 0x01E6); // LATIN SMALL LETTER G WITH CARON (LATIN SMALL LETTER G HACEK), LATIN CAPITAL LETTER G WITH CARON (LATIN CAPITAL LETTER G HACEK) +test(0x01E8, 0x01E9); // LATIN CAPITAL LETTER K WITH CARON (LATIN CAPITAL LETTER K HACEK), LATIN SMALL LETTER K WITH CARON (LATIN SMALL LETTER K HACEK) +test(0x01E9, 0x01E8); // LATIN SMALL LETTER K WITH CARON (LATIN SMALL LETTER K HACEK), LATIN CAPITAL LETTER K WITH CARON (LATIN CAPITAL LETTER K HACEK) +test(0x01EA, 0x01EB); // LATIN CAPITAL LETTER O WITH OGONEK (LATIN CAPITAL LETTER O OGONEK), LATIN SMALL LETTER O WITH OGONEK (LATIN SMALL LETTER O OGONEK) +test(0x01EB, 0x01EA); // LATIN SMALL LETTER O WITH OGONEK (LATIN SMALL LETTER O OGONEK), LATIN CAPITAL LETTER O WITH OGONEK (LATIN CAPITAL LETTER O OGONEK) +test(0x01EC, 0x01ED); // LATIN CAPITAL LETTER O WITH OGONEK AND MACRON (LATIN CAPITAL LETTER O OGONEK MACRON), LATIN SMALL LETTER O WITH OGONEK AND MACRON (LATIN SMALL LETTER O OGONEK MACRON) +test(0x01ED, 0x01EC); // LATIN SMALL LETTER O WITH OGONEK AND MACRON (LATIN SMALL LETTER O OGONEK MACRON), LATIN CAPITAL LETTER O WITH OGONEK AND MACRON (LATIN CAPITAL LETTER O OGONEK MACRON) +test(0x01EE, 0x01EF); // LATIN CAPITAL LETTER EZH WITH CARON (LATIN CAPITAL LETTER YOGH HACEK), LATIN SMALL LETTER EZH WITH CARON (LATIN SMALL LETTER YOGH HACEK) +test(0x01EF, 0x01EE); // LATIN SMALL LETTER EZH WITH CARON (LATIN SMALL LETTER YOGH HACEK), LATIN CAPITAL LETTER EZH WITH CARON (LATIN CAPITAL LETTER YOGH HACEK) +test(0x01F1, 0x01F3, 0x01F2); // LATIN CAPITAL LETTER DZ, LATIN SMALL LETTER DZ, LATIN CAPITAL LETTER D WITH SMALL LETTER Z +test(0x01F2, 0x01F3, 0x01F1); // LATIN CAPITAL LETTER D WITH SMALL LETTER Z, LATIN SMALL LETTER DZ, LATIN CAPITAL LETTER DZ +test(0x01F3, 0x01F1, 0x01F2); // LATIN SMALL LETTER DZ, LATIN CAPITAL LETTER DZ, LATIN CAPITAL LETTER D WITH SMALL LETTER Z +test(0x01F4, 0x01F5); // LATIN CAPITAL LETTER G WITH ACUTE, LATIN SMALL LETTER G WITH ACUTE +test(0x01F5, 0x01F4); // LATIN SMALL LETTER G WITH ACUTE, LATIN CAPITAL LETTER G WITH ACUTE +test(0x01F6, 0x0195); // LATIN CAPITAL LETTER HWAIR, LATIN SMALL LETTER HV (LATIN SMALL LETTER H V) +test(0x01F7, 0x01BF); // LATIN CAPITAL LETTER WYNN, LATIN LETTER WYNN +test(0x01F8, 0x01F9); // LATIN CAPITAL LETTER N WITH GRAVE, LATIN SMALL LETTER N WITH GRAVE +test(0x01F9, 0x01F8); // LATIN SMALL LETTER N WITH GRAVE, LATIN CAPITAL LETTER N WITH GRAVE +test(0x01FA, 0x01FB); // LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE, LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE +test(0x01FB, 0x01FA); // LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE, LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE +test(0x01FC, 0x01FD); // LATIN CAPITAL LETTER AE WITH ACUTE, LATIN SMALL LETTER AE WITH ACUTE +test(0x01FD, 0x01FC); // LATIN SMALL LETTER AE WITH ACUTE, LATIN CAPITAL LETTER AE WITH ACUTE +test(0x01FE, 0x01FF); // LATIN CAPITAL LETTER O WITH STROKE AND ACUTE, LATIN SMALL LETTER O WITH STROKE AND ACUTE +test(0x01FF, 0x01FE); // LATIN SMALL LETTER O WITH STROKE AND ACUTE, LATIN CAPITAL LETTER O WITH STROKE AND ACUTE +test(0x0200, 0x0201); // LATIN CAPITAL LETTER A WITH DOUBLE GRAVE, LATIN SMALL LETTER A WITH DOUBLE GRAVE +test(0x0201, 0x0200); // LATIN SMALL LETTER A WITH DOUBLE GRAVE, LATIN CAPITAL LETTER A WITH DOUBLE GRAVE +test(0x0202, 0x0203); // LATIN CAPITAL LETTER A WITH INVERTED BREVE, LATIN SMALL LETTER A WITH INVERTED BREVE +test(0x0203, 0x0202); // LATIN SMALL LETTER A WITH INVERTED BREVE, LATIN CAPITAL LETTER A WITH INVERTED BREVE +test(0x0204, 0x0205); // LATIN CAPITAL LETTER E WITH DOUBLE GRAVE, LATIN SMALL LETTER E WITH DOUBLE GRAVE +test(0x0205, 0x0204); // LATIN SMALL LETTER E WITH DOUBLE GRAVE, LATIN CAPITAL LETTER E WITH DOUBLE GRAVE +test(0x0206, 0x0207); // LATIN CAPITAL LETTER E WITH INVERTED BREVE, LATIN SMALL LETTER E WITH INVERTED BREVE +test(0x0207, 0x0206); // LATIN SMALL LETTER E WITH INVERTED BREVE, LATIN CAPITAL LETTER E WITH INVERTED BREVE +test(0x0208, 0x0209); // LATIN CAPITAL LETTER I WITH DOUBLE GRAVE, LATIN SMALL LETTER I WITH DOUBLE GRAVE +test(0x0209, 0x0208); // LATIN SMALL LETTER I WITH DOUBLE GRAVE, LATIN CAPITAL LETTER I WITH DOUBLE GRAVE +test(0x020A, 0x020B); // LATIN CAPITAL LETTER I WITH INVERTED BREVE, LATIN SMALL LETTER I WITH INVERTED BREVE +test(0x020B, 0x020A); // LATIN SMALL LETTER I WITH INVERTED BREVE, LATIN CAPITAL LETTER I WITH INVERTED BREVE +test(0x020C, 0x020D); // LATIN CAPITAL LETTER O WITH DOUBLE GRAVE, LATIN SMALL LETTER O WITH DOUBLE GRAVE +test(0x020D, 0x020C); // LATIN SMALL LETTER O WITH DOUBLE GRAVE, LATIN CAPITAL LETTER O WITH DOUBLE GRAVE +test(0x020E, 0x020F); // LATIN CAPITAL LETTER O WITH INVERTED BREVE, LATIN SMALL LETTER O WITH INVERTED BREVE +test(0x020F, 0x020E); // LATIN SMALL LETTER O WITH INVERTED BREVE, LATIN CAPITAL LETTER O WITH INVERTED BREVE +test(0x0210, 0x0211); // LATIN CAPITAL LETTER R WITH DOUBLE GRAVE, LATIN SMALL LETTER R WITH DOUBLE GRAVE +test(0x0211, 0x0210); // LATIN SMALL LETTER R WITH DOUBLE GRAVE, LATIN CAPITAL LETTER R WITH DOUBLE GRAVE +test(0x0212, 0x0213); // LATIN CAPITAL LETTER R WITH INVERTED BREVE, LATIN SMALL LETTER R WITH INVERTED BREVE +test(0x0213, 0x0212); // LATIN SMALL LETTER R WITH INVERTED BREVE, LATIN CAPITAL LETTER R WITH INVERTED BREVE +test(0x0214, 0x0215); // LATIN CAPITAL LETTER U WITH DOUBLE GRAVE, LATIN SMALL LETTER U WITH DOUBLE GRAVE +test(0x0215, 0x0214); // LATIN SMALL LETTER U WITH DOUBLE GRAVE, LATIN CAPITAL LETTER U WITH DOUBLE GRAVE +test(0x0216, 0x0217); // LATIN CAPITAL LETTER U WITH INVERTED BREVE, LATIN SMALL LETTER U WITH INVERTED BREVE +test(0x0217, 0x0216); // LATIN SMALL LETTER U WITH INVERTED BREVE, LATIN CAPITAL LETTER U WITH INVERTED BREVE +test(0x0218, 0x0219); // LATIN CAPITAL LETTER S WITH COMMA BELOW, LATIN SMALL LETTER S WITH COMMA BELOW +test(0x0219, 0x0218); // LATIN SMALL LETTER S WITH COMMA BELOW, LATIN CAPITAL LETTER S WITH COMMA BELOW +test(0x021A, 0x021B); // LATIN CAPITAL LETTER T WITH COMMA BELOW, LATIN SMALL LETTER T WITH COMMA BELOW +test(0x021B, 0x021A); // LATIN SMALL LETTER T WITH COMMA BELOW, LATIN CAPITAL LETTER T WITH COMMA BELOW +test(0x021C, 0x021D); // LATIN CAPITAL LETTER YOGH, LATIN SMALL LETTER YOGH +test(0x021D, 0x021C); // LATIN SMALL LETTER YOGH, LATIN CAPITAL LETTER YOGH +test(0x021E, 0x021F); // LATIN CAPITAL LETTER H WITH CARON, LATIN SMALL LETTER H WITH CARON +test(0x021F, 0x021E); // LATIN SMALL LETTER H WITH CARON, LATIN CAPITAL LETTER H WITH CARON +test(0x0220, 0x019E); // LATIN CAPITAL LETTER N WITH LONG RIGHT LEG, LATIN SMALL LETTER N WITH LONG RIGHT LEG +test(0x0222, 0x0223); // LATIN CAPITAL LETTER OU, LATIN SMALL LETTER OU +test(0x0223, 0x0222); // LATIN SMALL LETTER OU, LATIN CAPITAL LETTER OU +test(0x0224, 0x0225); // LATIN CAPITAL LETTER Z WITH HOOK, LATIN SMALL LETTER Z WITH HOOK +test(0x0225, 0x0224); // LATIN SMALL LETTER Z WITH HOOK, LATIN CAPITAL LETTER Z WITH HOOK +test(0x0226, 0x0227); // LATIN CAPITAL LETTER A WITH DOT ABOVE, LATIN SMALL LETTER A WITH DOT ABOVE +test(0x0227, 0x0226); // LATIN SMALL LETTER A WITH DOT ABOVE, LATIN CAPITAL LETTER A WITH DOT ABOVE +test(0x0228, 0x0229); // LATIN CAPITAL LETTER E WITH CEDILLA, LATIN SMALL LETTER E WITH CEDILLA +test(0x0229, 0x0228); // LATIN SMALL LETTER E WITH CEDILLA, LATIN CAPITAL LETTER E WITH CEDILLA +test(0x022A, 0x022B); // LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON, LATIN SMALL LETTER O WITH DIAERESIS AND MACRON +test(0x022B, 0x022A); // LATIN SMALL LETTER O WITH DIAERESIS AND MACRON, LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON +test(0x022C, 0x022D); // LATIN CAPITAL LETTER O WITH TILDE AND MACRON, LATIN SMALL LETTER O WITH TILDE AND MACRON +test(0x022D, 0x022C); // LATIN SMALL LETTER O WITH TILDE AND MACRON, LATIN CAPITAL LETTER O WITH TILDE AND MACRON +test(0x022E, 0x022F); // LATIN CAPITAL LETTER O WITH DOT ABOVE, LATIN SMALL LETTER O WITH DOT ABOVE +test(0x022F, 0x022E); // LATIN SMALL LETTER O WITH DOT ABOVE, LATIN CAPITAL LETTER O WITH DOT ABOVE +test(0x0230, 0x0231); // LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON, LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON +test(0x0231, 0x0230); // LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON, LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON +test(0x0232, 0x0233); // LATIN CAPITAL LETTER Y WITH MACRON, LATIN SMALL LETTER Y WITH MACRON +test(0x0233, 0x0232); // LATIN SMALL LETTER Y WITH MACRON, LATIN CAPITAL LETTER Y WITH MACRON +test(0x023A, 0x2C65); // LATIN CAPITAL LETTER A WITH STROKE, LATIN SMALL LETTER A WITH STROKE +test(0x023B, 0x023C); // LATIN CAPITAL LETTER C WITH STROKE, LATIN SMALL LETTER C WITH STROKE +test(0x023C, 0x023B); // LATIN SMALL LETTER C WITH STROKE, LATIN CAPITAL LETTER C WITH STROKE +test(0x023D, 0x019A); // LATIN CAPITAL LETTER L WITH BAR, LATIN SMALL LETTER L WITH BAR (LATIN SMALL LETTER BARRED L) +test(0x023E, 0x2C66); // LATIN CAPITAL LETTER T WITH DIAGONAL STROKE, LATIN SMALL LETTER T WITH DIAGONAL STROKE +test(0x023F, 0x2C7E); // LATIN SMALL LETTER S WITH SWASH TAIL, LATIN CAPITAL LETTER S WITH SWASH TAIL +test(0x0240, 0x2C7F); // LATIN SMALL LETTER Z WITH SWASH TAIL, LATIN CAPITAL LETTER Z WITH SWASH TAIL +test(0x0241, 0x0242); // LATIN CAPITAL LETTER GLOTTAL STOP, LATIN SMALL LETTER GLOTTAL STOP +test(0x0242, 0x0241); // LATIN SMALL LETTER GLOTTAL STOP, LATIN CAPITAL LETTER GLOTTAL STOP +test(0x0243, 0x0180); // LATIN CAPITAL LETTER B WITH STROKE, LATIN SMALL LETTER B WITH STROKE (LATIN SMALL LETTER B BAR) +test(0x0244, 0x0289); // LATIN CAPITAL LETTER U BAR, LATIN SMALL LETTER U BAR +test(0x0245, 0x028C); // LATIN CAPITAL LETTER TURNED V, LATIN SMALL LETTER TURNED V +test(0x0246, 0x0247); // LATIN CAPITAL LETTER E WITH STROKE, LATIN SMALL LETTER E WITH STROKE +test(0x0247, 0x0246); // LATIN SMALL LETTER E WITH STROKE, LATIN CAPITAL LETTER E WITH STROKE +test(0x0248, 0x0249); // LATIN CAPITAL LETTER J WITH STROKE, LATIN SMALL LETTER J WITH STROKE +test(0x0249, 0x0248); // LATIN SMALL LETTER J WITH STROKE, LATIN CAPITAL LETTER J WITH STROKE +test(0x024A, 0x024B); // LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL, LATIN SMALL LETTER Q WITH HOOK TAIL +test(0x024B, 0x024A); // LATIN SMALL LETTER Q WITH HOOK TAIL, LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL +test(0x024C, 0x024D); // LATIN CAPITAL LETTER R WITH STROKE, LATIN SMALL LETTER R WITH STROKE +test(0x024D, 0x024C); // LATIN SMALL LETTER R WITH STROKE, LATIN CAPITAL LETTER R WITH STROKE +test(0x024E, 0x024F); // LATIN CAPITAL LETTER Y WITH STROKE, LATIN SMALL LETTER Y WITH STROKE +test(0x024F, 0x024E); // LATIN SMALL LETTER Y WITH STROKE, LATIN CAPITAL LETTER Y WITH STROKE +test(0x0250, 0x2C6F); // LATIN SMALL LETTER TURNED A, LATIN CAPITAL LETTER TURNED A +test(0x0251, 0x2C6D); // LATIN SMALL LETTER ALPHA (LATIN SMALL LETTER SCRIPT A), LATIN CAPITAL LETTER ALPHA +test(0x0252, 0x2C70); // LATIN SMALL LETTER TURNED ALPHA (LATIN SMALL LETTER TURNED SCRIPT A), LATIN CAPITAL LETTER TURNED ALPHA +test(0x0253, 0x0181); // LATIN SMALL LETTER B WITH HOOK (LATIN SMALL LETTER B HOOK), LATIN CAPITAL LETTER B WITH HOOK (LATIN CAPITAL LETTER B HOOK) +test(0x0254, 0x0186); // LATIN SMALL LETTER OPEN O, LATIN CAPITAL LETTER OPEN O +test(0x0256, 0x0189); // LATIN SMALL LETTER D WITH TAIL (LATIN SMALL LETTER D RETROFLEX HOOK), LATIN CAPITAL LETTER AFRICAN D +test(0x0257, 0x018A); // LATIN SMALL LETTER D WITH HOOK (LATIN SMALL LETTER D HOOK), LATIN CAPITAL LETTER D WITH HOOK (LATIN CAPITAL LETTER D HOOK) +test(0x0259, 0x018F); // LATIN SMALL LETTER SCHWA, LATIN CAPITAL LETTER SCHWA +test(0x025B, 0x0190); // LATIN SMALL LETTER OPEN E (LATIN SMALL LETTER EPSILON), LATIN CAPITAL LETTER OPEN E (LATIN CAPITAL LETTER EPSILON) +test(0x025C, 0xA7AB); // LATIN SMALL LETTER REVERSED OPEN E (LATIN SMALL LETTER REVERSED EPSILON), LATIN CAPITAL LETTER REVERSED OPEN E +test(0x0260, 0x0193); // LATIN SMALL LETTER G WITH HOOK (LATIN SMALL LETTER G HOOK), LATIN CAPITAL LETTER G WITH HOOK (LATIN CAPITAL LETTER G HOOK) +test(0x0261, 0xA7AC); // LATIN SMALL LETTER SCRIPT G, LATIN CAPITAL LETTER SCRIPT G +test(0x0263, 0x0194); // LATIN SMALL LETTER GAMMA, LATIN CAPITAL LETTER GAMMA +test(0x0265, 0xA78D); // LATIN SMALL LETTER TURNED H, LATIN CAPITAL LETTER TURNED H +test(0x0266, 0xA7AA); // LATIN SMALL LETTER H WITH HOOK (LATIN SMALL LETTER H HOOK), LATIN CAPITAL LETTER H WITH HOOK +test(0x0268, 0x0197); // LATIN SMALL LETTER I WITH STROKE (LATIN SMALL LETTER BARRED I), LATIN CAPITAL LETTER I WITH STROKE (LATIN CAPITAL LETTER BARRED I) +test(0x0269, 0x0196); // LATIN SMALL LETTER IOTA, LATIN CAPITAL LETTER IOTA +test(0x026A, 0xA7AE); // LATIN LETTER SMALL CAPITAL I, LATIN CAPITAL LETTER SMALL CAPITAL I +test(0x026B, 0x2C62); // LATIN SMALL LETTER L WITH MIDDLE TILDE, LATIN CAPITAL LETTER L WITH MIDDLE TILDE +test(0x026C, 0xA7AD); // LATIN SMALL LETTER L WITH BELT (LATIN SMALL LETTER L BELT), LATIN CAPITAL LETTER L WITH BELT +test(0x026F, 0x019C); // LATIN SMALL LETTER TURNED M, LATIN CAPITAL LETTER TURNED M +test(0x0271, 0x2C6E); // LATIN SMALL LETTER M WITH HOOK (LATIN SMALL LETTER M HOOK), LATIN CAPITAL LETTER M WITH HOOK +test(0x0272, 0x019D); // LATIN SMALL LETTER N WITH LEFT HOOK (LATIN SMALL LETTER N HOOK), LATIN CAPITAL LETTER N WITH LEFT HOOK (LATIN CAPITAL LETTER N HOOK) +test(0x0275, 0x019F); // LATIN SMALL LETTER BARRED O, LATIN CAPITAL LETTER O WITH MIDDLE TILDE (LATIN CAPITAL LETTER BARRED O) +test(0x027D, 0x2C64); // LATIN SMALL LETTER R WITH TAIL (LATIN SMALL LETTER R HOOK), LATIN CAPITAL LETTER R WITH TAIL +test(0x0280, 0x01A6); // LATIN LETTER SMALL CAPITAL R, LATIN LETTER YR (LATIN LETTER Y R) +test(0x0282, 0xA7C5); // LATIN SMALL LETTER S WITH HOOK (LATIN SMALL LETTER S HOOK), LATIN CAPITAL LETTER S WITH HOOK +test(0x0283, 0x01A9); // LATIN SMALL LETTER ESH, LATIN CAPITAL LETTER ESH +test(0x0287, 0xA7B1); // LATIN SMALL LETTER TURNED T, LATIN CAPITAL LETTER TURNED T +test(0x0288, 0x01AE); // LATIN SMALL LETTER T WITH RETROFLEX HOOK (LATIN SMALL LETTER T RETROFLEX HOOK), LATIN CAPITAL LETTER T WITH RETROFLEX HOOK (LATIN CAPITAL LETTER T RETROFLEX HOOK) +test(0x0289, 0x0244); // LATIN SMALL LETTER U BAR, LATIN CAPITAL LETTER U BAR +test(0x028A, 0x01B1); // LATIN SMALL LETTER UPSILON, LATIN CAPITAL LETTER UPSILON +test(0x028B, 0x01B2); // LATIN SMALL LETTER V WITH HOOK (LATIN SMALL LETTER SCRIPT V), LATIN CAPITAL LETTER V WITH HOOK (LATIN CAPITAL LETTER SCRIPT V) +test(0x028C, 0x0245); // LATIN SMALL LETTER TURNED V, LATIN CAPITAL LETTER TURNED V +test(0x0292, 0x01B7); // LATIN SMALL LETTER EZH (LATIN SMALL LETTER YOGH), LATIN CAPITAL LETTER EZH (LATIN CAPITAL LETTER YOGH) +test(0x029D, 0xA7B2); // LATIN SMALL LETTER J WITH CROSSED-TAIL (LATIN SMALL LETTER CROSSED-TAIL J), LATIN CAPITAL LETTER J WITH CROSSED-TAIL +test(0x029E, 0xA7B0); // LATIN SMALL LETTER TURNED K, LATIN CAPITAL LETTER TURNED K +test(0x0345, 0x03B9, 0x0399, 0x1FBE); // COMBINING GREEK YPOGEGRAMMENI (GREEK NON-SPACING IOTA BELOW), GREEK SMALL LETTER IOTA, GREEK CAPITAL LETTER IOTA, GREEK PROSGEGRAMMENI +test(0x0370, 0x0371); // GREEK CAPITAL LETTER HETA, GREEK SMALL LETTER HETA +test(0x0371, 0x0370); // GREEK SMALL LETTER HETA, GREEK CAPITAL LETTER HETA +test(0x0372, 0x0373); // GREEK CAPITAL LETTER ARCHAIC SAMPI, GREEK SMALL LETTER ARCHAIC SAMPI +test(0x0373, 0x0372); // GREEK SMALL LETTER ARCHAIC SAMPI, GREEK CAPITAL LETTER ARCHAIC SAMPI +test(0x0376, 0x0377); // GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA, GREEK SMALL LETTER PAMPHYLIAN DIGAMMA +test(0x0377, 0x0376); // GREEK SMALL LETTER PAMPHYLIAN DIGAMMA, GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA +test(0x037B, 0x03FD); // GREEK SMALL REVERSED LUNATE SIGMA SYMBOL, GREEK CAPITAL REVERSED LUNATE SIGMA SYMBOL +test(0x037C, 0x03FE); // GREEK SMALL DOTTED LUNATE SIGMA SYMBOL, GREEK CAPITAL DOTTED LUNATE SIGMA SYMBOL +test(0x037D, 0x03FF); // GREEK SMALL REVERSED DOTTED LUNATE SIGMA SYMBOL, GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL +test(0x037F, 0x03F3); // GREEK CAPITAL LETTER YOT, GREEK LETTER YOT +test(0x0386, 0x03AC); // GREEK CAPITAL LETTER ALPHA WITH TONOS (GREEK CAPITAL LETTER ALPHA TONOS), GREEK SMALL LETTER ALPHA WITH TONOS (GREEK SMALL LETTER ALPHA TONOS) +test(0x0388, 0x03AD); // GREEK CAPITAL LETTER EPSILON WITH TONOS (GREEK CAPITAL LETTER EPSILON TONOS), GREEK SMALL LETTER EPSILON WITH TONOS (GREEK SMALL LETTER EPSILON TONOS) +test(0x0389, 0x03AE); // GREEK CAPITAL LETTER ETA WITH TONOS (GREEK CAPITAL LETTER ETA TONOS), GREEK SMALL LETTER ETA WITH TONOS (GREEK SMALL LETTER ETA TONOS) +test(0x038A, 0x03AF); // GREEK CAPITAL LETTER IOTA WITH TONOS (GREEK CAPITAL LETTER IOTA TONOS), GREEK SMALL LETTER IOTA WITH TONOS (GREEK SMALL LETTER IOTA TONOS) +test(0x038C, 0x03CC); // GREEK CAPITAL LETTER OMICRON WITH TONOS (GREEK CAPITAL LETTER OMICRON TONOS), GREEK SMALL LETTER OMICRON WITH TONOS (GREEK SMALL LETTER OMICRON TONOS) +test(0x038E, 0x03CD); // GREEK CAPITAL LETTER UPSILON WITH TONOS (GREEK CAPITAL LETTER UPSILON TONOS), GREEK SMALL LETTER UPSILON WITH TONOS (GREEK SMALL LETTER UPSILON TONOS) +test(0x038F, 0x03CE); // GREEK CAPITAL LETTER OMEGA WITH TONOS (GREEK CAPITAL LETTER OMEGA TONOS), GREEK SMALL LETTER OMEGA WITH TONOS (GREEK SMALL LETTER OMEGA TONOS) +test(0x0391, 0x03B1); // GREEK CAPITAL LETTER ALPHA, GREEK SMALL LETTER ALPHA +test(0x0392, 0x03B2, 0x03D0); // GREEK CAPITAL LETTER BETA, GREEK SMALL LETTER BETA, GREEK BETA SYMBOL (GREEK SMALL LETTER CURLED BETA) +test(0x0393, 0x03B3); // GREEK CAPITAL LETTER GAMMA, GREEK SMALL LETTER GAMMA +test(0x0394, 0x03B4); // GREEK CAPITAL LETTER DELTA, GREEK SMALL LETTER DELTA +test(0x0395, 0x03B5, 0x03F5); // GREEK CAPITAL LETTER EPSILON, GREEK SMALL LETTER EPSILON, GREEK LUNATE EPSILON SYMBOL +test(0x0396, 0x03B6); // GREEK CAPITAL LETTER ZETA, GREEK SMALL LETTER ZETA +test(0x0397, 0x03B7); // GREEK CAPITAL LETTER ETA, GREEK SMALL LETTER ETA +test(0x0398, 0x03B8, 0x03D1, 0x03F4); // GREEK CAPITAL LETTER THETA, GREEK SMALL LETTER THETA, GREEK THETA SYMBOL (GREEK SMALL LETTER SCRIPT THETA), GREEK CAPITAL THETA SYMBOL +test(0x0399, 0x03B9, 0x0345, 0x1FBE); // GREEK CAPITAL LETTER IOTA, GREEK SMALL LETTER IOTA, COMBINING GREEK YPOGEGRAMMENI (GREEK NON-SPACING IOTA BELOW), GREEK PROSGEGRAMMENI +test(0x039A, 0x03BA, 0x03F0); // GREEK CAPITAL LETTER KAPPA, GREEK SMALL LETTER KAPPA, GREEK KAPPA SYMBOL (GREEK SMALL LETTER SCRIPT KAPPA) +test(0x039B, 0x03BB); // GREEK CAPITAL LETTER LAMDA (GREEK CAPITAL LETTER LAMBDA), GREEK SMALL LETTER LAMDA (GREEK SMALL LETTER LAMBDA) +test(0x039C, 0x03BC, 0x00B5); // GREEK CAPITAL LETTER MU, GREEK SMALL LETTER MU, MICRO SIGN +test(0x039D, 0x03BD); // GREEK CAPITAL LETTER NU, GREEK SMALL LETTER NU +test(0x039E, 0x03BE); // GREEK CAPITAL LETTER XI, GREEK SMALL LETTER XI +test(0x039F, 0x03BF); // GREEK CAPITAL LETTER OMICRON, GREEK SMALL LETTER OMICRON +test(0x03A0, 0x03C0, 0x03D6); // GREEK CAPITAL LETTER PI, GREEK SMALL LETTER PI, GREEK PI SYMBOL (GREEK SMALL LETTER OMEGA PI) +test(0x03A1, 0x03C1, 0x03F1); // GREEK CAPITAL LETTER RHO, GREEK SMALL LETTER RHO, GREEK RHO SYMBOL (GREEK SMALL LETTER TAILED RHO) +test(0x03A3, 0x03C3, 0x03C2); // GREEK CAPITAL LETTER SIGMA, GREEK SMALL LETTER SIGMA, GREEK SMALL LETTER FINAL SIGMA +test(0x03A4, 0x03C4); // GREEK CAPITAL LETTER TAU, GREEK SMALL LETTER TAU +test(0x03A5, 0x03C5); // GREEK CAPITAL LETTER UPSILON, GREEK SMALL LETTER UPSILON +test(0x03A6, 0x03C6, 0x03D5); // GREEK CAPITAL LETTER PHI, GREEK SMALL LETTER PHI, GREEK PHI SYMBOL (GREEK SMALL LETTER SCRIPT PHI) +test(0x03A7, 0x03C7); // GREEK CAPITAL LETTER CHI, GREEK SMALL LETTER CHI +test(0x03A8, 0x03C8); // GREEK CAPITAL LETTER PSI, GREEK SMALL LETTER PSI +test(0x03A9, 0x03C9, 0x2126); // GREEK CAPITAL LETTER OMEGA, GREEK SMALL LETTER OMEGA, OHM SIGN (OHM) +test(0x03AA, 0x03CA); // GREEK CAPITAL LETTER IOTA WITH DIALYTIKA (GREEK CAPITAL LETTER IOTA DIAERESIS), GREEK SMALL LETTER IOTA WITH DIALYTIKA (GREEK SMALL LETTER IOTA DIAERESIS) +test(0x03AB, 0x03CB); // GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA (GREEK CAPITAL LETTER UPSILON DIAERESIS), GREEK SMALL LETTER UPSILON WITH DIALYTIKA (GREEK SMALL LETTER UPSILON DIAERESIS) +test(0x03AC, 0x0386); // GREEK SMALL LETTER ALPHA WITH TONOS (GREEK SMALL LETTER ALPHA TONOS), GREEK CAPITAL LETTER ALPHA WITH TONOS (GREEK CAPITAL LETTER ALPHA TONOS) +test(0x03AD, 0x0388); // GREEK SMALL LETTER EPSILON WITH TONOS (GREEK SMALL LETTER EPSILON TONOS), GREEK CAPITAL LETTER EPSILON WITH TONOS (GREEK CAPITAL LETTER EPSILON TONOS) +test(0x03AE, 0x0389); // GREEK SMALL LETTER ETA WITH TONOS (GREEK SMALL LETTER ETA TONOS), GREEK CAPITAL LETTER ETA WITH TONOS (GREEK CAPITAL LETTER ETA TONOS) +test(0x03AF, 0x038A); // GREEK SMALL LETTER IOTA WITH TONOS (GREEK SMALL LETTER IOTA TONOS), GREEK CAPITAL LETTER IOTA WITH TONOS (GREEK CAPITAL LETTER IOTA TONOS) +test(0x03B1, 0x0391); // GREEK SMALL LETTER ALPHA, GREEK CAPITAL LETTER ALPHA +test(0x03B2, 0x0392, 0x03D0); // GREEK SMALL LETTER BETA, GREEK CAPITAL LETTER BETA, GREEK BETA SYMBOL (GREEK SMALL LETTER CURLED BETA) +test(0x03B3, 0x0393); // GREEK SMALL LETTER GAMMA, GREEK CAPITAL LETTER GAMMA +test(0x03B4, 0x0394); // GREEK SMALL LETTER DELTA, GREEK CAPITAL LETTER DELTA +test(0x03B5, 0x0395, 0x03F5); // GREEK SMALL LETTER EPSILON, GREEK CAPITAL LETTER EPSILON, GREEK LUNATE EPSILON SYMBOL +test(0x03B6, 0x0396); // GREEK SMALL LETTER ZETA, GREEK CAPITAL LETTER ZETA +test(0x03B7, 0x0397); // GREEK SMALL LETTER ETA, GREEK CAPITAL LETTER ETA +test(0x03B8, 0x0398, 0x03D1, 0x03F4); // GREEK SMALL LETTER THETA, GREEK CAPITAL LETTER THETA, GREEK THETA SYMBOL (GREEK SMALL LETTER SCRIPT THETA), GREEK CAPITAL THETA SYMBOL +test(0x03B9, 0x0345, 0x0399, 0x1FBE); // GREEK SMALL LETTER IOTA, COMBINING GREEK YPOGEGRAMMENI (GREEK NON-SPACING IOTA BELOW), GREEK CAPITAL LETTER IOTA, GREEK PROSGEGRAMMENI +test(0x03BA, 0x039A, 0x03F0); // GREEK SMALL LETTER KAPPA, GREEK CAPITAL LETTER KAPPA, GREEK KAPPA SYMBOL (GREEK SMALL LETTER SCRIPT KAPPA) +test(0x03BB, 0x039B); // GREEK SMALL LETTER LAMDA (GREEK SMALL LETTER LAMBDA), GREEK CAPITAL LETTER LAMDA (GREEK CAPITAL LETTER LAMBDA) +test(0x03BC, 0x00B5, 0x039C); // GREEK SMALL LETTER MU, MICRO SIGN, GREEK CAPITAL LETTER MU +test(0x03BD, 0x039D); // GREEK SMALL LETTER NU, GREEK CAPITAL LETTER NU +test(0x03BE, 0x039E); // GREEK SMALL LETTER XI, GREEK CAPITAL LETTER XI +test(0x03BF, 0x039F); // GREEK SMALL LETTER OMICRON, GREEK CAPITAL LETTER OMICRON +test(0x03C0, 0x03A0, 0x03D6); // GREEK SMALL LETTER PI, GREEK CAPITAL LETTER PI, GREEK PI SYMBOL (GREEK SMALL LETTER OMEGA PI) +test(0x03C1, 0x03A1, 0x03F1); // GREEK SMALL LETTER RHO, GREEK CAPITAL LETTER RHO, GREEK RHO SYMBOL (GREEK SMALL LETTER TAILED RHO) +test(0x03C2, 0x03C3, 0x03A3); // GREEK SMALL LETTER FINAL SIGMA, GREEK SMALL LETTER SIGMA, GREEK CAPITAL LETTER SIGMA +test(0x03C3, 0x03A3, 0x03C2); // GREEK SMALL LETTER SIGMA, GREEK CAPITAL LETTER SIGMA, GREEK SMALL LETTER FINAL SIGMA +test(0x03C4, 0x03A4); // GREEK SMALL LETTER TAU, GREEK CAPITAL LETTER TAU +test(0x03C5, 0x03A5); // GREEK SMALL LETTER UPSILON, GREEK CAPITAL LETTER UPSILON +test(0x03C6, 0x03A6, 0x03D5); // GREEK SMALL LETTER PHI, GREEK CAPITAL LETTER PHI, GREEK PHI SYMBOL (GREEK SMALL LETTER SCRIPT PHI) +test(0x03C7, 0x03A7); // GREEK SMALL LETTER CHI, GREEK CAPITAL LETTER CHI +test(0x03C8, 0x03A8); // GREEK SMALL LETTER PSI, GREEK CAPITAL LETTER PSI +test(0x03C9, 0x03A9, 0x2126); // GREEK SMALL LETTER OMEGA, GREEK CAPITAL LETTER OMEGA, OHM SIGN (OHM) +test(0x03CA, 0x03AA); // GREEK SMALL LETTER IOTA WITH DIALYTIKA (GREEK SMALL LETTER IOTA DIAERESIS), GREEK CAPITAL LETTER IOTA WITH DIALYTIKA (GREEK CAPITAL LETTER IOTA DIAERESIS) +test(0x03CB, 0x03AB); // GREEK SMALL LETTER UPSILON WITH DIALYTIKA (GREEK SMALL LETTER UPSILON DIAERESIS), GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA (GREEK CAPITAL LETTER UPSILON DIAERESIS) +test(0x03CC, 0x038C); // GREEK SMALL LETTER OMICRON WITH TONOS (GREEK SMALL LETTER OMICRON TONOS), GREEK CAPITAL LETTER OMICRON WITH TONOS (GREEK CAPITAL LETTER OMICRON TONOS) +test(0x03CD, 0x038E); // GREEK SMALL LETTER UPSILON WITH TONOS (GREEK SMALL LETTER UPSILON TONOS), GREEK CAPITAL LETTER UPSILON WITH TONOS (GREEK CAPITAL LETTER UPSILON TONOS) +test(0x03CE, 0x038F); // GREEK SMALL LETTER OMEGA WITH TONOS (GREEK SMALL LETTER OMEGA TONOS), GREEK CAPITAL LETTER OMEGA WITH TONOS (GREEK CAPITAL LETTER OMEGA TONOS) +test(0x03CF, 0x03D7); // GREEK CAPITAL KAI SYMBOL, GREEK KAI SYMBOL +test(0x03D0, 0x03B2, 0x0392); // GREEK BETA SYMBOL (GREEK SMALL LETTER CURLED BETA), GREEK SMALL LETTER BETA, GREEK CAPITAL LETTER BETA +test(0x03D1, 0x03B8, 0x0398, 0x03F4); // GREEK THETA SYMBOL (GREEK SMALL LETTER SCRIPT THETA), GREEK SMALL LETTER THETA, GREEK CAPITAL LETTER THETA, GREEK CAPITAL THETA SYMBOL +test(0x03D5, 0x03C6, 0x03A6); // GREEK PHI SYMBOL (GREEK SMALL LETTER SCRIPT PHI), GREEK SMALL LETTER PHI, GREEK CAPITAL LETTER PHI +test(0x03D6, 0x03C0, 0x03A0); // GREEK PI SYMBOL (GREEK SMALL LETTER OMEGA PI), GREEK SMALL LETTER PI, GREEK CAPITAL LETTER PI +test(0x03D7, 0x03CF); // GREEK KAI SYMBOL, GREEK CAPITAL KAI SYMBOL +test(0x03D8, 0x03D9); // GREEK LETTER ARCHAIC KOPPA, GREEK SMALL LETTER ARCHAIC KOPPA +test(0x03D9, 0x03D8); // GREEK SMALL LETTER ARCHAIC KOPPA, GREEK LETTER ARCHAIC KOPPA +test(0x03DA, 0x03DB); // GREEK LETTER STIGMA (GREEK CAPITAL LETTER STIGMA), GREEK SMALL LETTER STIGMA +test(0x03DB, 0x03DA); // GREEK SMALL LETTER STIGMA, GREEK LETTER STIGMA (GREEK CAPITAL LETTER STIGMA) +test(0x03DC, 0x03DD); // GREEK LETTER DIGAMMA (GREEK CAPITAL LETTER DIGAMMA), GREEK SMALL LETTER DIGAMMA +test(0x03DD, 0x03DC); // GREEK SMALL LETTER DIGAMMA, GREEK LETTER DIGAMMA (GREEK CAPITAL LETTER DIGAMMA) +test(0x03DE, 0x03DF); // GREEK LETTER KOPPA (GREEK CAPITAL LETTER KOPPA), GREEK SMALL LETTER KOPPA +test(0x03DF, 0x03DE); // GREEK SMALL LETTER KOPPA, GREEK LETTER KOPPA (GREEK CAPITAL LETTER KOPPA) +test(0x03E0, 0x03E1); // GREEK LETTER SAMPI (GREEK CAPITAL LETTER SAMPI), GREEK SMALL LETTER SAMPI +test(0x03E1, 0x03E0); // GREEK SMALL LETTER SAMPI, GREEK LETTER SAMPI (GREEK CAPITAL LETTER SAMPI) +test(0x03E2, 0x03E3); // COPTIC CAPITAL LETTER SHEI (GREEK CAPITAL LETTER SHEI), COPTIC SMALL LETTER SHEI (GREEK SMALL LETTER SHEI) +test(0x03E3, 0x03E2); // COPTIC SMALL LETTER SHEI (GREEK SMALL LETTER SHEI), COPTIC CAPITAL LETTER SHEI (GREEK CAPITAL LETTER SHEI) +test(0x03E4, 0x03E5); // COPTIC CAPITAL LETTER FEI (GREEK CAPITAL LETTER FEI), COPTIC SMALL LETTER FEI (GREEK SMALL LETTER FEI) +test(0x03E5, 0x03E4); // COPTIC SMALL LETTER FEI (GREEK SMALL LETTER FEI), COPTIC CAPITAL LETTER FEI (GREEK CAPITAL LETTER FEI) +test(0x03E6, 0x03E7); // COPTIC CAPITAL LETTER KHEI (GREEK CAPITAL LETTER KHEI), COPTIC SMALL LETTER KHEI (GREEK SMALL LETTER KHEI) +test(0x03E7, 0x03E6); // COPTIC SMALL LETTER KHEI (GREEK SMALL LETTER KHEI), COPTIC CAPITAL LETTER KHEI (GREEK CAPITAL LETTER KHEI) +test(0x03E8, 0x03E9); // COPTIC CAPITAL LETTER HORI (GREEK CAPITAL LETTER HORI), COPTIC SMALL LETTER HORI (GREEK SMALL LETTER HORI) +test(0x03E9, 0x03E8); // COPTIC SMALL LETTER HORI (GREEK SMALL LETTER HORI), COPTIC CAPITAL LETTER HORI (GREEK CAPITAL LETTER HORI) +test(0x03EA, 0x03EB); // COPTIC CAPITAL LETTER GANGIA (GREEK CAPITAL LETTER GANGIA), COPTIC SMALL LETTER GANGIA (GREEK SMALL LETTER GANGIA) +test(0x03EB, 0x03EA); // COPTIC SMALL LETTER GANGIA (GREEK SMALL LETTER GANGIA), COPTIC CAPITAL LETTER GANGIA (GREEK CAPITAL LETTER GANGIA) +test(0x03EC, 0x03ED); // COPTIC CAPITAL LETTER SHIMA (GREEK CAPITAL LETTER SHIMA), COPTIC SMALL LETTER SHIMA (GREEK SMALL LETTER SHIMA) +test(0x03ED, 0x03EC); // COPTIC SMALL LETTER SHIMA (GREEK SMALL LETTER SHIMA), COPTIC CAPITAL LETTER SHIMA (GREEK CAPITAL LETTER SHIMA) +test(0x03EE, 0x03EF); // COPTIC CAPITAL LETTER DEI (GREEK CAPITAL LETTER DEI), COPTIC SMALL LETTER DEI (GREEK SMALL LETTER DEI) +test(0x03EF, 0x03EE); // COPTIC SMALL LETTER DEI (GREEK SMALL LETTER DEI), COPTIC CAPITAL LETTER DEI (GREEK CAPITAL LETTER DEI) +test(0x03F0, 0x03BA, 0x039A); // GREEK KAPPA SYMBOL (GREEK SMALL LETTER SCRIPT KAPPA), GREEK SMALL LETTER KAPPA, GREEK CAPITAL LETTER KAPPA +test(0x03F1, 0x03C1, 0x03A1); // GREEK RHO SYMBOL (GREEK SMALL LETTER TAILED RHO), GREEK SMALL LETTER RHO, GREEK CAPITAL LETTER RHO +test(0x03F2, 0x03F9); // GREEK LUNATE SIGMA SYMBOL (GREEK SMALL LETTER LUNATE SIGMA), GREEK CAPITAL LUNATE SIGMA SYMBOL +test(0x03F3, 0x037F); // GREEK LETTER YOT, GREEK CAPITAL LETTER YOT +test(0x03F4, 0x03B8, 0x0398, 0x03D1); // GREEK CAPITAL THETA SYMBOL, GREEK SMALL LETTER THETA, GREEK CAPITAL LETTER THETA, GREEK THETA SYMBOL (GREEK SMALL LETTER SCRIPT THETA) +test(0x03F5, 0x03B5, 0x0395); // GREEK LUNATE EPSILON SYMBOL, GREEK SMALL LETTER EPSILON, GREEK CAPITAL LETTER EPSILON +test(0x03F7, 0x03F8); // GREEK CAPITAL LETTER SHO, GREEK SMALL LETTER SHO +test(0x03F8, 0x03F7); // GREEK SMALL LETTER SHO, GREEK CAPITAL LETTER SHO +test(0x03F9, 0x03F2); // GREEK CAPITAL LUNATE SIGMA SYMBOL, GREEK LUNATE SIGMA SYMBOL (GREEK SMALL LETTER LUNATE SIGMA) +test(0x03FA, 0x03FB); // GREEK CAPITAL LETTER SAN, GREEK SMALL LETTER SAN +test(0x03FB, 0x03FA); // GREEK SMALL LETTER SAN, GREEK CAPITAL LETTER SAN +test(0x03FD, 0x037B); // GREEK CAPITAL REVERSED LUNATE SIGMA SYMBOL, GREEK SMALL REVERSED LUNATE SIGMA SYMBOL +test(0x03FE, 0x037C); // GREEK CAPITAL DOTTED LUNATE SIGMA SYMBOL, GREEK SMALL DOTTED LUNATE SIGMA SYMBOL +test(0x03FF, 0x037D); // GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL, GREEK SMALL REVERSED DOTTED LUNATE SIGMA SYMBOL +test(0x0400, 0x0450); // CYRILLIC CAPITAL LETTER IE WITH GRAVE, CYRILLIC SMALL LETTER IE WITH GRAVE +test(0x0401, 0x0451); // CYRILLIC CAPITAL LETTER IO, CYRILLIC SMALL LETTER IO +test(0x0402, 0x0452); // CYRILLIC CAPITAL LETTER DJE, CYRILLIC SMALL LETTER DJE +test(0x0403, 0x0453); // CYRILLIC CAPITAL LETTER GJE, CYRILLIC SMALL LETTER GJE +test(0x0404, 0x0454); // CYRILLIC CAPITAL LETTER UKRAINIAN IE (CYRILLIC CAPITAL LETTER E), CYRILLIC SMALL LETTER UKRAINIAN IE (CYRILLIC SMALL LETTER E) +test(0x0405, 0x0455); // CYRILLIC CAPITAL LETTER DZE, CYRILLIC SMALL LETTER DZE +test(0x0406, 0x0456); // CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I (CYRILLIC CAPITAL LETTER I), CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I (CYRILLIC SMALL LETTER I) +test(0x0407, 0x0457); // CYRILLIC CAPITAL LETTER YI, CYRILLIC SMALL LETTER YI +test(0x0408, 0x0458); // CYRILLIC CAPITAL LETTER JE, CYRILLIC SMALL LETTER JE +test(0x0409, 0x0459); // CYRILLIC CAPITAL LETTER LJE, CYRILLIC SMALL LETTER LJE +test(0x040A, 0x045A); // CYRILLIC CAPITAL LETTER NJE, CYRILLIC SMALL LETTER NJE +test(0x040B, 0x045B); // CYRILLIC CAPITAL LETTER TSHE, CYRILLIC SMALL LETTER TSHE +test(0x040C, 0x045C); // CYRILLIC CAPITAL LETTER KJE, CYRILLIC SMALL LETTER KJE +test(0x040D, 0x045D); // CYRILLIC CAPITAL LETTER I WITH GRAVE, CYRILLIC SMALL LETTER I WITH GRAVE +test(0x040E, 0x045E); // CYRILLIC CAPITAL LETTER SHORT U, CYRILLIC SMALL LETTER SHORT U +test(0x040F, 0x045F); // CYRILLIC CAPITAL LETTER DZHE, CYRILLIC SMALL LETTER DZHE +test(0x0410, 0x0430); // CYRILLIC CAPITAL LETTER A, CYRILLIC SMALL LETTER A +test(0x0411, 0x0431); // CYRILLIC CAPITAL LETTER BE, CYRILLIC SMALL LETTER BE +test(0x0412, 0x0432, 0x1C80); // CYRILLIC CAPITAL LETTER VE, CYRILLIC SMALL LETTER VE, CYRILLIC SMALL LETTER ROUNDED VE +test(0x0413, 0x0433); // CYRILLIC CAPITAL LETTER GHE (CYRILLIC CAPITAL LETTER GE), CYRILLIC SMALL LETTER GHE (CYRILLIC SMALL LETTER GE) +test(0x0414, 0x0434, 0x1C81); // CYRILLIC CAPITAL LETTER DE, CYRILLIC SMALL LETTER DE, CYRILLIC SMALL LETTER LONG-LEGGED DE +test(0x0415, 0x0435); // CYRILLIC CAPITAL LETTER IE, CYRILLIC SMALL LETTER IE +test(0x0416, 0x0436); // CYRILLIC CAPITAL LETTER ZHE, CYRILLIC SMALL LETTER ZHE +test(0x0417, 0x0437); // CYRILLIC CAPITAL LETTER ZE, CYRILLIC SMALL LETTER ZE +test(0x0418, 0x0438); // CYRILLIC CAPITAL LETTER I (CYRILLIC CAPITAL LETTER II), CYRILLIC SMALL LETTER I (CYRILLIC SMALL LETTER II) +test(0x0419, 0x0439); // CYRILLIC CAPITAL LETTER SHORT I (CYRILLIC CAPITAL LETTER SHORT II), CYRILLIC SMALL LETTER SHORT I (CYRILLIC SMALL LETTER SHORT II) +test(0x041A, 0x043A); // CYRILLIC CAPITAL LETTER KA, CYRILLIC SMALL LETTER KA +test(0x041B, 0x043B); // CYRILLIC CAPITAL LETTER EL, CYRILLIC SMALL LETTER EL +test(0x041C, 0x043C); // CYRILLIC CAPITAL LETTER EM, CYRILLIC SMALL LETTER EM +test(0x041D, 0x043D); // CYRILLIC CAPITAL LETTER EN, CYRILLIC SMALL LETTER EN +test(0x041E, 0x043E, 0x1C82); // CYRILLIC CAPITAL LETTER O, CYRILLIC SMALL LETTER O, CYRILLIC SMALL LETTER NARROW O +test(0x041F, 0x043F); // CYRILLIC CAPITAL LETTER PE, CYRILLIC SMALL LETTER PE +test(0x0420, 0x0440); // CYRILLIC CAPITAL LETTER ER, CYRILLIC SMALL LETTER ER +test(0x0421, 0x0441, 0x1C83); // CYRILLIC CAPITAL LETTER ES, CYRILLIC SMALL LETTER ES, CYRILLIC SMALL LETTER WIDE ES +test(0x0422, 0x0442, 0x1C84, 0x1C85); // CYRILLIC CAPITAL LETTER TE, CYRILLIC SMALL LETTER TE, CYRILLIC SMALL LETTER TALL TE, CYRILLIC SMALL LETTER THREE-LEGGED TE +test(0x0423, 0x0443); // CYRILLIC CAPITAL LETTER U, CYRILLIC SMALL LETTER U +test(0x0424, 0x0444); // CYRILLIC CAPITAL LETTER EF, CYRILLIC SMALL LETTER EF +test(0x0425, 0x0445); // CYRILLIC CAPITAL LETTER HA (CYRILLIC CAPITAL LETTER KHA), CYRILLIC SMALL LETTER HA (CYRILLIC SMALL LETTER KHA) +test(0x0426, 0x0446); // CYRILLIC CAPITAL LETTER TSE, CYRILLIC SMALL LETTER TSE +test(0x0427, 0x0447); // CYRILLIC CAPITAL LETTER CHE, CYRILLIC SMALL LETTER CHE +test(0x0428, 0x0448); // CYRILLIC CAPITAL LETTER SHA, CYRILLIC SMALL LETTER SHA +test(0x0429, 0x0449); // CYRILLIC CAPITAL LETTER SHCHA, CYRILLIC SMALL LETTER SHCHA +test(0x042A, 0x044A, 0x1C86); // CYRILLIC CAPITAL LETTER HARD SIGN, CYRILLIC SMALL LETTER HARD SIGN, CYRILLIC SMALL LETTER TALL HARD SIGN +test(0x042B, 0x044B); // CYRILLIC CAPITAL LETTER YERU (CYRILLIC CAPITAL LETTER YERI), CYRILLIC SMALL LETTER YERU (CYRILLIC SMALL LETTER YERI) +test(0x042C, 0x044C); // CYRILLIC CAPITAL LETTER SOFT SIGN, CYRILLIC SMALL LETTER SOFT SIGN +test(0x042D, 0x044D); // CYRILLIC CAPITAL LETTER E (CYRILLIC CAPITAL LETTER REVERSED E), CYRILLIC SMALL LETTER E (CYRILLIC SMALL LETTER REVERSED E) +test(0x042E, 0x044E); // CYRILLIC CAPITAL LETTER YU (CYRILLIC CAPITAL LETTER IU), CYRILLIC SMALL LETTER YU (CYRILLIC SMALL LETTER IU) +test(0x042F, 0x044F); // CYRILLIC CAPITAL LETTER YA (CYRILLIC CAPITAL LETTER IA), CYRILLIC SMALL LETTER YA (CYRILLIC SMALL LETTER IA) +test(0x0430, 0x0410); // CYRILLIC SMALL LETTER A, CYRILLIC CAPITAL LETTER A +test(0x0431, 0x0411); // CYRILLIC SMALL LETTER BE, CYRILLIC CAPITAL LETTER BE +test(0x0432, 0x0412, 0x1C80); // CYRILLIC SMALL LETTER VE, CYRILLIC CAPITAL LETTER VE, CYRILLIC SMALL LETTER ROUNDED VE +test(0x0433, 0x0413); // CYRILLIC SMALL LETTER GHE (CYRILLIC SMALL LETTER GE), CYRILLIC CAPITAL LETTER GHE (CYRILLIC CAPITAL LETTER GE) +test(0x0434, 0x0414, 0x1C81); // CYRILLIC SMALL LETTER DE, CYRILLIC CAPITAL LETTER DE, CYRILLIC SMALL LETTER LONG-LEGGED DE +test(0x0435, 0x0415); // CYRILLIC SMALL LETTER IE, CYRILLIC CAPITAL LETTER IE +test(0x0436, 0x0416); // CYRILLIC SMALL LETTER ZHE, CYRILLIC CAPITAL LETTER ZHE +test(0x0437, 0x0417); // CYRILLIC SMALL LETTER ZE, CYRILLIC CAPITAL LETTER ZE +test(0x0438, 0x0418); // CYRILLIC SMALL LETTER I (CYRILLIC SMALL LETTER II), CYRILLIC CAPITAL LETTER I (CYRILLIC CAPITAL LETTER II) +test(0x0439, 0x0419); // CYRILLIC SMALL LETTER SHORT I (CYRILLIC SMALL LETTER SHORT II), CYRILLIC CAPITAL LETTER SHORT I (CYRILLIC CAPITAL LETTER SHORT II) +test(0x043A, 0x041A); // CYRILLIC SMALL LETTER KA, CYRILLIC CAPITAL LETTER KA +test(0x043B, 0x041B); // CYRILLIC SMALL LETTER EL, CYRILLIC CAPITAL LETTER EL +test(0x043C, 0x041C); // CYRILLIC SMALL LETTER EM, CYRILLIC CAPITAL LETTER EM +test(0x043D, 0x041D); // CYRILLIC SMALL LETTER EN, CYRILLIC CAPITAL LETTER EN +test(0x043E, 0x041E, 0x1C82); // CYRILLIC SMALL LETTER O, CYRILLIC CAPITAL LETTER O, CYRILLIC SMALL LETTER NARROW O +test(0x043F, 0x041F); // CYRILLIC SMALL LETTER PE, CYRILLIC CAPITAL LETTER PE +test(0x0440, 0x0420); // CYRILLIC SMALL LETTER ER, CYRILLIC CAPITAL LETTER ER +test(0x0441, 0x0421, 0x1C83); // CYRILLIC SMALL LETTER ES, CYRILLIC CAPITAL LETTER ES, CYRILLIC SMALL LETTER WIDE ES +test(0x0442, 0x0422, 0x1C84, 0x1C85); // CYRILLIC SMALL LETTER TE, CYRILLIC CAPITAL LETTER TE, CYRILLIC SMALL LETTER TALL TE, CYRILLIC SMALL LETTER THREE-LEGGED TE +test(0x0443, 0x0423); // CYRILLIC SMALL LETTER U, CYRILLIC CAPITAL LETTER U +test(0x0444, 0x0424); // CYRILLIC SMALL LETTER EF, CYRILLIC CAPITAL LETTER EF +test(0x0445, 0x0425); // CYRILLIC SMALL LETTER HA (CYRILLIC SMALL LETTER KHA), CYRILLIC CAPITAL LETTER HA (CYRILLIC CAPITAL LETTER KHA) +test(0x0446, 0x0426); // CYRILLIC SMALL LETTER TSE, CYRILLIC CAPITAL LETTER TSE +test(0x0447, 0x0427); // CYRILLIC SMALL LETTER CHE, CYRILLIC CAPITAL LETTER CHE +test(0x0448, 0x0428); // CYRILLIC SMALL LETTER SHA, CYRILLIC CAPITAL LETTER SHA +test(0x0449, 0x0429); // CYRILLIC SMALL LETTER SHCHA, CYRILLIC CAPITAL LETTER SHCHA +test(0x044A, 0x042A, 0x1C86); // CYRILLIC SMALL LETTER HARD SIGN, CYRILLIC CAPITAL LETTER HARD SIGN, CYRILLIC SMALL LETTER TALL HARD SIGN +test(0x044B, 0x042B); // CYRILLIC SMALL LETTER YERU (CYRILLIC SMALL LETTER YERI), CYRILLIC CAPITAL LETTER YERU (CYRILLIC CAPITAL LETTER YERI) +test(0x044C, 0x042C); // CYRILLIC SMALL LETTER SOFT SIGN, CYRILLIC CAPITAL LETTER SOFT SIGN +test(0x044D, 0x042D); // CYRILLIC SMALL LETTER E (CYRILLIC SMALL LETTER REVERSED E), CYRILLIC CAPITAL LETTER E (CYRILLIC CAPITAL LETTER REVERSED E) +test(0x044E, 0x042E); // CYRILLIC SMALL LETTER YU (CYRILLIC SMALL LETTER IU), CYRILLIC CAPITAL LETTER YU (CYRILLIC CAPITAL LETTER IU) +test(0x044F, 0x042F); // CYRILLIC SMALL LETTER YA (CYRILLIC SMALL LETTER IA), CYRILLIC CAPITAL LETTER YA (CYRILLIC CAPITAL LETTER IA) +test(0x0450, 0x0400); // CYRILLIC SMALL LETTER IE WITH GRAVE, CYRILLIC CAPITAL LETTER IE WITH GRAVE +test(0x0451, 0x0401); // CYRILLIC SMALL LETTER IO, CYRILLIC CAPITAL LETTER IO +test(0x0452, 0x0402); // CYRILLIC SMALL LETTER DJE, CYRILLIC CAPITAL LETTER DJE +test(0x0453, 0x0403); // CYRILLIC SMALL LETTER GJE, CYRILLIC CAPITAL LETTER GJE +test(0x0454, 0x0404); // CYRILLIC SMALL LETTER UKRAINIAN IE (CYRILLIC SMALL LETTER E), CYRILLIC CAPITAL LETTER UKRAINIAN IE (CYRILLIC CAPITAL LETTER E) +test(0x0455, 0x0405); // CYRILLIC SMALL LETTER DZE, CYRILLIC CAPITAL LETTER DZE +test(0x0456, 0x0406); // CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I (CYRILLIC SMALL LETTER I), CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I (CYRILLIC CAPITAL LETTER I) +test(0x0457, 0x0407); // CYRILLIC SMALL LETTER YI, CYRILLIC CAPITAL LETTER YI +test(0x0458, 0x0408); // CYRILLIC SMALL LETTER JE, CYRILLIC CAPITAL LETTER JE +test(0x0459, 0x0409); // CYRILLIC SMALL LETTER LJE, CYRILLIC CAPITAL LETTER LJE +test(0x045A, 0x040A); // CYRILLIC SMALL LETTER NJE, CYRILLIC CAPITAL LETTER NJE +test(0x045B, 0x040B); // CYRILLIC SMALL LETTER TSHE, CYRILLIC CAPITAL LETTER TSHE +test(0x045C, 0x040C); // CYRILLIC SMALL LETTER KJE, CYRILLIC CAPITAL LETTER KJE +test(0x045D, 0x040D); // CYRILLIC SMALL LETTER I WITH GRAVE, CYRILLIC CAPITAL LETTER I WITH GRAVE +test(0x045E, 0x040E); // CYRILLIC SMALL LETTER SHORT U, CYRILLIC CAPITAL LETTER SHORT U +test(0x045F, 0x040F); // CYRILLIC SMALL LETTER DZHE, CYRILLIC CAPITAL LETTER DZHE +test(0x0460, 0x0461); // CYRILLIC CAPITAL LETTER OMEGA, CYRILLIC SMALL LETTER OMEGA +test(0x0461, 0x0460); // CYRILLIC SMALL LETTER OMEGA, CYRILLIC CAPITAL LETTER OMEGA +test(0x0462, 0x0463, 0x1C87); // CYRILLIC CAPITAL LETTER YAT, CYRILLIC SMALL LETTER YAT, CYRILLIC SMALL LETTER TALL YAT +test(0x0463, 0x0462, 0x1C87); // CYRILLIC SMALL LETTER YAT, CYRILLIC CAPITAL LETTER YAT, CYRILLIC SMALL LETTER TALL YAT +test(0x0464, 0x0465); // CYRILLIC CAPITAL LETTER IOTIFIED E, CYRILLIC SMALL LETTER IOTIFIED E +test(0x0465, 0x0464); // CYRILLIC SMALL LETTER IOTIFIED E, CYRILLIC CAPITAL LETTER IOTIFIED E +test(0x0466, 0x0467); // CYRILLIC CAPITAL LETTER LITTLE YUS, CYRILLIC SMALL LETTER LITTLE YUS +test(0x0467, 0x0466); // CYRILLIC SMALL LETTER LITTLE YUS, CYRILLIC CAPITAL LETTER LITTLE YUS +test(0x0468, 0x0469); // CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS, CYRILLIC SMALL LETTER IOTIFIED LITTLE YUS +test(0x0469, 0x0468); // CYRILLIC SMALL LETTER IOTIFIED LITTLE YUS, CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS +test(0x046A, 0x046B); // CYRILLIC CAPITAL LETTER BIG YUS, CYRILLIC SMALL LETTER BIG YUS +test(0x046B, 0x046A); // CYRILLIC SMALL LETTER BIG YUS, CYRILLIC CAPITAL LETTER BIG YUS +test(0x046C, 0x046D); // CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS, CYRILLIC SMALL LETTER IOTIFIED BIG YUS +test(0x046D, 0x046C); // CYRILLIC SMALL LETTER IOTIFIED BIG YUS, CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS +test(0x046E, 0x046F); // CYRILLIC CAPITAL LETTER KSI, CYRILLIC SMALL LETTER KSI +test(0x046F, 0x046E); // CYRILLIC SMALL LETTER KSI, CYRILLIC CAPITAL LETTER KSI +test(0x0470, 0x0471); // CYRILLIC CAPITAL LETTER PSI, CYRILLIC SMALL LETTER PSI +test(0x0471, 0x0470); // CYRILLIC SMALL LETTER PSI, CYRILLIC CAPITAL LETTER PSI +test(0x0472, 0x0473); // CYRILLIC CAPITAL LETTER FITA, CYRILLIC SMALL LETTER FITA +test(0x0473, 0x0472); // CYRILLIC SMALL LETTER FITA, CYRILLIC CAPITAL LETTER FITA +test(0x0474, 0x0475); // CYRILLIC CAPITAL LETTER IZHITSA, CYRILLIC SMALL LETTER IZHITSA +test(0x0475, 0x0474); // CYRILLIC SMALL LETTER IZHITSA, CYRILLIC CAPITAL LETTER IZHITSA +test(0x0476, 0x0477); // CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT (CYRILLIC CAPITAL LETTER IZHITSA DOUBLE GRAVE), CYRILLIC SMALL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT (CYRILLIC SMALL LETTER IZHITSA DOUBLE GRAVE) +test(0x0477, 0x0476); // CYRILLIC SMALL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT (CYRILLIC SMALL LETTER IZHITSA DOUBLE GRAVE), CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT (CYRILLIC CAPITAL LETTER IZHITSA DOUBLE GRAVE) +test(0x0478, 0x0479); // CYRILLIC CAPITAL LETTER UK (CYRILLIC CAPITAL LETTER UK DIGRAPH), CYRILLIC SMALL LETTER UK (CYRILLIC SMALL LETTER UK DIGRAPH) +test(0x0479, 0x0478); // CYRILLIC SMALL LETTER UK (CYRILLIC SMALL LETTER UK DIGRAPH), CYRILLIC CAPITAL LETTER UK (CYRILLIC CAPITAL LETTER UK DIGRAPH) +test(0x047A, 0x047B); // CYRILLIC CAPITAL LETTER ROUND OMEGA, CYRILLIC SMALL LETTER ROUND OMEGA +test(0x047B, 0x047A); // CYRILLIC SMALL LETTER ROUND OMEGA, CYRILLIC CAPITAL LETTER ROUND OMEGA +test(0x047C, 0x047D); // CYRILLIC CAPITAL LETTER OMEGA WITH TITLO (CYRILLIC CAPITAL LETTER OMEGA TITLO), CYRILLIC SMALL LETTER OMEGA WITH TITLO (CYRILLIC SMALL LETTER OMEGA TITLO) +test(0x047D, 0x047C); // CYRILLIC SMALL LETTER OMEGA WITH TITLO (CYRILLIC SMALL LETTER OMEGA TITLO), CYRILLIC CAPITAL LETTER OMEGA WITH TITLO (CYRILLIC CAPITAL LETTER OMEGA TITLO) +test(0x047E, 0x047F); // CYRILLIC CAPITAL LETTER OT, CYRILLIC SMALL LETTER OT +test(0x047F, 0x047E); // CYRILLIC SMALL LETTER OT, CYRILLIC CAPITAL LETTER OT +test(0x0480, 0x0481); // CYRILLIC CAPITAL LETTER KOPPA, CYRILLIC SMALL LETTER KOPPA +test(0x0481, 0x0480); // CYRILLIC SMALL LETTER KOPPA, CYRILLIC CAPITAL LETTER KOPPA +test(0x048A, 0x048B); // CYRILLIC CAPITAL LETTER SHORT I WITH TAIL, CYRILLIC SMALL LETTER SHORT I WITH TAIL +test(0x048B, 0x048A); // CYRILLIC SMALL LETTER SHORT I WITH TAIL, CYRILLIC CAPITAL LETTER SHORT I WITH TAIL +test(0x048C, 0x048D); // CYRILLIC CAPITAL LETTER SEMISOFT SIGN, CYRILLIC SMALL LETTER SEMISOFT SIGN +test(0x048D, 0x048C); // CYRILLIC SMALL LETTER SEMISOFT SIGN, CYRILLIC CAPITAL LETTER SEMISOFT SIGN +test(0x048E, 0x048F); // CYRILLIC CAPITAL LETTER ER WITH TICK, CYRILLIC SMALL LETTER ER WITH TICK +test(0x048F, 0x048E); // CYRILLIC SMALL LETTER ER WITH TICK, CYRILLIC CAPITAL LETTER ER WITH TICK +test(0x0490, 0x0491); // CYRILLIC CAPITAL LETTER GHE WITH UPTURN (CYRILLIC CAPITAL LETTER GE WITH UPTURN), CYRILLIC SMALL LETTER GHE WITH UPTURN (CYRILLIC SMALL LETTER GE WITH UPTURN) +test(0x0491, 0x0490); // CYRILLIC SMALL LETTER GHE WITH UPTURN (CYRILLIC SMALL LETTER GE WITH UPTURN), CYRILLIC CAPITAL LETTER GHE WITH UPTURN (CYRILLIC CAPITAL LETTER GE WITH UPTURN) +test(0x0492, 0x0493); // CYRILLIC CAPITAL LETTER GHE WITH STROKE (CYRILLIC CAPITAL LETTER GE BAR), CYRILLIC SMALL LETTER GHE WITH STROKE (CYRILLIC SMALL LETTER GE BAR) +test(0x0493, 0x0492); // CYRILLIC SMALL LETTER GHE WITH STROKE (CYRILLIC SMALL LETTER GE BAR), CYRILLIC CAPITAL LETTER GHE WITH STROKE (CYRILLIC CAPITAL LETTER GE BAR) +test(0x0494, 0x0495); // CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK (CYRILLIC CAPITAL LETTER GE HOOK), CYRILLIC SMALL LETTER GHE WITH MIDDLE HOOK (CYRILLIC SMALL LETTER GE HOOK) +test(0x0495, 0x0494); // CYRILLIC SMALL LETTER GHE WITH MIDDLE HOOK (CYRILLIC SMALL LETTER GE HOOK), CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK (CYRILLIC CAPITAL LETTER GE HOOK) +test(0x0496, 0x0497); // CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER (CYRILLIC CAPITAL LETTER ZHE WITH RIGHT DESCENDER), CYRILLIC SMALL LETTER ZHE WITH DESCENDER (CYRILLIC SMALL LETTER ZHE WITH RIGHT DESCENDER) +test(0x0497, 0x0496); // CYRILLIC SMALL LETTER ZHE WITH DESCENDER (CYRILLIC SMALL LETTER ZHE WITH RIGHT DESCENDER), CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER (CYRILLIC CAPITAL LETTER ZHE WITH RIGHT DESCENDER) +test(0x0498, 0x0499); // CYRILLIC CAPITAL LETTER ZE WITH DESCENDER (CYRILLIC CAPITAL LETTER ZE CEDILLA), CYRILLIC SMALL LETTER ZE WITH DESCENDER (CYRILLIC SMALL LETTER ZE CEDILLA) +test(0x0499, 0x0498); // CYRILLIC SMALL LETTER ZE WITH DESCENDER (CYRILLIC SMALL LETTER ZE CEDILLA), CYRILLIC CAPITAL LETTER ZE WITH DESCENDER (CYRILLIC CAPITAL LETTER ZE CEDILLA) +test(0x049A, 0x049B); // CYRILLIC CAPITAL LETTER KA WITH DESCENDER (CYRILLIC CAPITAL LETTER KA WITH RIGHT DESCENDER), CYRILLIC SMALL LETTER KA WITH DESCENDER (CYRILLIC SMALL LETTER KA WITH RIGHT DESCENDER) +test(0x049B, 0x049A); // CYRILLIC SMALL LETTER KA WITH DESCENDER (CYRILLIC SMALL LETTER KA WITH RIGHT DESCENDER), CYRILLIC CAPITAL LETTER KA WITH DESCENDER (CYRILLIC CAPITAL LETTER KA WITH RIGHT DESCENDER) +test(0x049C, 0x049D); // CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE (CYRILLIC CAPITAL LETTER KA VERTICAL BAR), CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE (CYRILLIC SMALL LETTER KA VERTICAL BAR) +test(0x049D, 0x049C); // CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE (CYRILLIC SMALL LETTER KA VERTICAL BAR), CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE (CYRILLIC CAPITAL LETTER KA VERTICAL BAR) +test(0x049E, 0x049F); // CYRILLIC CAPITAL LETTER KA WITH STROKE (CYRILLIC CAPITAL LETTER KA BAR), CYRILLIC SMALL LETTER KA WITH STROKE (CYRILLIC SMALL LETTER KA BAR) +test(0x049F, 0x049E); // CYRILLIC SMALL LETTER KA WITH STROKE (CYRILLIC SMALL LETTER KA BAR), CYRILLIC CAPITAL LETTER KA WITH STROKE (CYRILLIC CAPITAL LETTER KA BAR) +test(0x04A0, 0x04A1); // CYRILLIC CAPITAL LETTER BASHKIR KA (CYRILLIC CAPITAL LETTER REVERSED GE KA), CYRILLIC SMALL LETTER BASHKIR KA (CYRILLIC SMALL LETTER REVERSED GE KA) +test(0x04A1, 0x04A0); // CYRILLIC SMALL LETTER BASHKIR KA (CYRILLIC SMALL LETTER REVERSED GE KA), CYRILLIC CAPITAL LETTER BASHKIR KA (CYRILLIC CAPITAL LETTER REVERSED GE KA) +test(0x04A2, 0x04A3); // CYRILLIC CAPITAL LETTER EN WITH DESCENDER (CYRILLIC CAPITAL LETTER EN WITH RIGHT DESCENDER), CYRILLIC SMALL LETTER EN WITH DESCENDER (CYRILLIC SMALL LETTER EN WITH RIGHT DESCENDER) +test(0x04A3, 0x04A2); // CYRILLIC SMALL LETTER EN WITH DESCENDER (CYRILLIC SMALL LETTER EN WITH RIGHT DESCENDER), CYRILLIC CAPITAL LETTER EN WITH DESCENDER (CYRILLIC CAPITAL LETTER EN WITH RIGHT DESCENDER) +test(0x04A4, 0x04A5); // CYRILLIC CAPITAL LIGATURE EN GHE (CYRILLIC CAPITAL LETTER EN GE), CYRILLIC SMALL LIGATURE EN GHE (CYRILLIC SMALL LETTER EN GE) +test(0x04A5, 0x04A4); // CYRILLIC SMALL LIGATURE EN GHE (CYRILLIC SMALL LETTER EN GE), CYRILLIC CAPITAL LIGATURE EN GHE (CYRILLIC CAPITAL LETTER EN GE) +test(0x04A6, 0x04A7); // CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK (CYRILLIC CAPITAL LETTER PE HOOK), CYRILLIC SMALL LETTER PE WITH MIDDLE HOOK (CYRILLIC SMALL LETTER PE HOOK) +test(0x04A7, 0x04A6); // CYRILLIC SMALL LETTER PE WITH MIDDLE HOOK (CYRILLIC SMALL LETTER PE HOOK), CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK (CYRILLIC CAPITAL LETTER PE HOOK) +test(0x04A8, 0x04A9); // CYRILLIC CAPITAL LETTER ABKHASIAN HA (CYRILLIC CAPITAL LETTER O HOOK), CYRILLIC SMALL LETTER ABKHASIAN HA (CYRILLIC SMALL LETTER O HOOK) +test(0x04A9, 0x04A8); // CYRILLIC SMALL LETTER ABKHASIAN HA (CYRILLIC SMALL LETTER O HOOK), CYRILLIC CAPITAL LETTER ABKHASIAN HA (CYRILLIC CAPITAL LETTER O HOOK) +test(0x04AA, 0x04AB); // CYRILLIC CAPITAL LETTER ES WITH DESCENDER (CYRILLIC CAPITAL LETTER ES CEDILLA), CYRILLIC SMALL LETTER ES WITH DESCENDER (CYRILLIC SMALL LETTER ES CEDILLA) +test(0x04AB, 0x04AA); // CYRILLIC SMALL LETTER ES WITH DESCENDER (CYRILLIC SMALL LETTER ES CEDILLA), CYRILLIC CAPITAL LETTER ES WITH DESCENDER (CYRILLIC CAPITAL LETTER ES CEDILLA) +test(0x04AC, 0x04AD); // CYRILLIC CAPITAL LETTER TE WITH DESCENDER (CYRILLIC CAPITAL LETTER TE WITH RIGHT DESCENDER), CYRILLIC SMALL LETTER TE WITH DESCENDER (CYRILLIC SMALL LETTER TE WITH RIGHT DESCENDER) +test(0x04AD, 0x04AC); // CYRILLIC SMALL LETTER TE WITH DESCENDER (CYRILLIC SMALL LETTER TE WITH RIGHT DESCENDER), CYRILLIC CAPITAL LETTER TE WITH DESCENDER (CYRILLIC CAPITAL LETTER TE WITH RIGHT DESCENDER) +test(0x04AE, 0x04AF); // CYRILLIC CAPITAL LETTER STRAIGHT U, CYRILLIC SMALL LETTER STRAIGHT U +test(0x04AF, 0x04AE); // CYRILLIC SMALL LETTER STRAIGHT U, CYRILLIC CAPITAL LETTER STRAIGHT U +test(0x04B0, 0x04B1); // CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE (CYRILLIC CAPITAL LETTER STRAIGHT U BAR), CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE (CYRILLIC SMALL LETTER STRAIGHT U BAR) +test(0x04B1, 0x04B0); // CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE (CYRILLIC SMALL LETTER STRAIGHT U BAR), CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE (CYRILLIC CAPITAL LETTER STRAIGHT U BAR) +test(0x04B2, 0x04B3); // CYRILLIC CAPITAL LETTER HA WITH DESCENDER (CYRILLIC CAPITAL LETTER KHA WITH RIGHT DESCENDER), CYRILLIC SMALL LETTER HA WITH DESCENDER (CYRILLIC SMALL LETTER KHA WITH RIGHT DESCENDER) +test(0x04B3, 0x04B2); // CYRILLIC SMALL LETTER HA WITH DESCENDER (CYRILLIC SMALL LETTER KHA WITH RIGHT DESCENDER), CYRILLIC CAPITAL LETTER HA WITH DESCENDER (CYRILLIC CAPITAL LETTER KHA WITH RIGHT DESCENDER) +test(0x04B4, 0x04B5); // CYRILLIC CAPITAL LIGATURE TE TSE (CYRILLIC CAPITAL LETTER TE TSE), CYRILLIC SMALL LIGATURE TE TSE (CYRILLIC SMALL LETTER TE TSE) +test(0x04B5, 0x04B4); // CYRILLIC SMALL LIGATURE TE TSE (CYRILLIC SMALL LETTER TE TSE), CYRILLIC CAPITAL LIGATURE TE TSE (CYRILLIC CAPITAL LETTER TE TSE) +test(0x04B6, 0x04B7); // CYRILLIC CAPITAL LETTER CHE WITH DESCENDER (CYRILLIC CAPITAL LETTER CHE WITH RIGHT DESCENDER), CYRILLIC SMALL LETTER CHE WITH DESCENDER (CYRILLIC SMALL LETTER CHE WITH RIGHT DESCENDER) +test(0x04B7, 0x04B6); // CYRILLIC SMALL LETTER CHE WITH DESCENDER (CYRILLIC SMALL LETTER CHE WITH RIGHT DESCENDER), CYRILLIC CAPITAL LETTER CHE WITH DESCENDER (CYRILLIC CAPITAL LETTER CHE WITH RIGHT DESCENDER) +test(0x04B8, 0x04B9); // CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE (CYRILLIC CAPITAL LETTER CHE VERTICAL BAR), CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE (CYRILLIC SMALL LETTER CHE VERTICAL BAR) +test(0x04B9, 0x04B8); // CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE (CYRILLIC SMALL LETTER CHE VERTICAL BAR), CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE (CYRILLIC CAPITAL LETTER CHE VERTICAL BAR) +test(0x04BA, 0x04BB); // CYRILLIC CAPITAL LETTER SHHA (CYRILLIC CAPITAL LETTER H), CYRILLIC SMALL LETTER SHHA (CYRILLIC SMALL LETTER H) +test(0x04BB, 0x04BA); // CYRILLIC SMALL LETTER SHHA (CYRILLIC SMALL LETTER H), CYRILLIC CAPITAL LETTER SHHA (CYRILLIC CAPITAL LETTER H) +test(0x04BC, 0x04BD); // CYRILLIC CAPITAL LETTER ABKHASIAN CHE (CYRILLIC CAPITAL LETTER IE HOOK), CYRILLIC SMALL LETTER ABKHASIAN CHE (CYRILLIC SMALL LETTER IE HOOK) +test(0x04BD, 0x04BC); // CYRILLIC SMALL LETTER ABKHASIAN CHE (CYRILLIC SMALL LETTER IE HOOK), CYRILLIC CAPITAL LETTER ABKHASIAN CHE (CYRILLIC CAPITAL LETTER IE HOOK) +test(0x04BE, 0x04BF); // CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER (CYRILLIC CAPITAL LETTER IE HOOK OGONEK), CYRILLIC SMALL LETTER ABKHASIAN CHE WITH DESCENDER (CYRILLIC SMALL LETTER IE HOOK OGONEK) +test(0x04BF, 0x04BE); // CYRILLIC SMALL LETTER ABKHASIAN CHE WITH DESCENDER (CYRILLIC SMALL LETTER IE HOOK OGONEK), CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER (CYRILLIC CAPITAL LETTER IE HOOK OGONEK) +test(0x04C0, 0x04CF); // CYRILLIC LETTER PALOCHKA (CYRILLIC LETTER I), CYRILLIC SMALL LETTER PALOCHKA +test(0x04C1, 0x04C2); // CYRILLIC CAPITAL LETTER ZHE WITH BREVE (CYRILLIC CAPITAL LETTER SHORT ZHE), CYRILLIC SMALL LETTER ZHE WITH BREVE (CYRILLIC SMALL LETTER SHORT ZHE) +test(0x04C2, 0x04C1); // CYRILLIC SMALL LETTER ZHE WITH BREVE (CYRILLIC SMALL LETTER SHORT ZHE), CYRILLIC CAPITAL LETTER ZHE WITH BREVE (CYRILLIC CAPITAL LETTER SHORT ZHE) +test(0x04C3, 0x04C4); // CYRILLIC CAPITAL LETTER KA WITH HOOK (CYRILLIC CAPITAL LETTER KA HOOK), CYRILLIC SMALL LETTER KA WITH HOOK (CYRILLIC SMALL LETTER KA HOOK) +test(0x04C4, 0x04C3); // CYRILLIC SMALL LETTER KA WITH HOOK (CYRILLIC SMALL LETTER KA HOOK), CYRILLIC CAPITAL LETTER KA WITH HOOK (CYRILLIC CAPITAL LETTER KA HOOK) +test(0x04C5, 0x04C6); // CYRILLIC CAPITAL LETTER EL WITH TAIL, CYRILLIC SMALL LETTER EL WITH TAIL +test(0x04C6, 0x04C5); // CYRILLIC SMALL LETTER EL WITH TAIL, CYRILLIC CAPITAL LETTER EL WITH TAIL +test(0x04C7, 0x04C8); // CYRILLIC CAPITAL LETTER EN WITH HOOK (CYRILLIC CAPITAL LETTER EN HOOK), CYRILLIC SMALL LETTER EN WITH HOOK (CYRILLIC SMALL LETTER EN HOOK) +test(0x04C8, 0x04C7); // CYRILLIC SMALL LETTER EN WITH HOOK (CYRILLIC SMALL LETTER EN HOOK), CYRILLIC CAPITAL LETTER EN WITH HOOK (CYRILLIC CAPITAL LETTER EN HOOK) +test(0x04C9, 0x04CA); // CYRILLIC CAPITAL LETTER EN WITH TAIL, CYRILLIC SMALL LETTER EN WITH TAIL +test(0x04CA, 0x04C9); // CYRILLIC SMALL LETTER EN WITH TAIL, CYRILLIC CAPITAL LETTER EN WITH TAIL +test(0x04CB, 0x04CC); // CYRILLIC CAPITAL LETTER KHAKASSIAN CHE (CYRILLIC CAPITAL LETTER CHE WITH LEFT DESCENDER), CYRILLIC SMALL LETTER KHAKASSIAN CHE (CYRILLIC SMALL LETTER CHE WITH LEFT DESCENDER) +test(0x04CC, 0x04CB); // CYRILLIC SMALL LETTER KHAKASSIAN CHE (CYRILLIC SMALL LETTER CHE WITH LEFT DESCENDER), CYRILLIC CAPITAL LETTER KHAKASSIAN CHE (CYRILLIC CAPITAL LETTER CHE WITH LEFT DESCENDER) +test(0x04CD, 0x04CE); // CYRILLIC CAPITAL LETTER EM WITH TAIL, CYRILLIC SMALL LETTER EM WITH TAIL +test(0x04CE, 0x04CD); // CYRILLIC SMALL LETTER EM WITH TAIL, CYRILLIC CAPITAL LETTER EM WITH TAIL +test(0x04CF, 0x04C0); // CYRILLIC SMALL LETTER PALOCHKA, CYRILLIC LETTER PALOCHKA (CYRILLIC LETTER I) +test(0x04D0, 0x04D1); // CYRILLIC CAPITAL LETTER A WITH BREVE, CYRILLIC SMALL LETTER A WITH BREVE +test(0x04D1, 0x04D0); // CYRILLIC SMALL LETTER A WITH BREVE, CYRILLIC CAPITAL LETTER A WITH BREVE +test(0x04D2, 0x04D3); // CYRILLIC CAPITAL LETTER A WITH DIAERESIS, CYRILLIC SMALL LETTER A WITH DIAERESIS +test(0x04D3, 0x04D2); // CYRILLIC SMALL LETTER A WITH DIAERESIS, CYRILLIC CAPITAL LETTER A WITH DIAERESIS +test(0x04D4, 0x04D5); // CYRILLIC CAPITAL LIGATURE A IE, CYRILLIC SMALL LIGATURE A IE +test(0x04D5, 0x04D4); // CYRILLIC SMALL LIGATURE A IE, CYRILLIC CAPITAL LIGATURE A IE +test(0x04D6, 0x04D7); // CYRILLIC CAPITAL LETTER IE WITH BREVE, CYRILLIC SMALL LETTER IE WITH BREVE +test(0x04D7, 0x04D6); // CYRILLIC SMALL LETTER IE WITH BREVE, CYRILLIC CAPITAL LETTER IE WITH BREVE +test(0x04D8, 0x04D9); // CYRILLIC CAPITAL LETTER SCHWA, CYRILLIC SMALL LETTER SCHWA +test(0x04D9, 0x04D8); // CYRILLIC SMALL LETTER SCHWA, CYRILLIC CAPITAL LETTER SCHWA +test(0x04DA, 0x04DB); // CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS, CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS +test(0x04DB, 0x04DA); // CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS, CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS +test(0x04DC, 0x04DD); // CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS, CYRILLIC SMALL LETTER ZHE WITH DIAERESIS +test(0x04DD, 0x04DC); // CYRILLIC SMALL LETTER ZHE WITH DIAERESIS, CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS +test(0x04DE, 0x04DF); // CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS, CYRILLIC SMALL LETTER ZE WITH DIAERESIS +test(0x04DF, 0x04DE); // CYRILLIC SMALL LETTER ZE WITH DIAERESIS, CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS +test(0x04E0, 0x04E1); // CYRILLIC CAPITAL LETTER ABKHASIAN DZE, CYRILLIC SMALL LETTER ABKHASIAN DZE +test(0x04E1, 0x04E0); // CYRILLIC SMALL LETTER ABKHASIAN DZE, CYRILLIC CAPITAL LETTER ABKHASIAN DZE +test(0x04E2, 0x04E3); // CYRILLIC CAPITAL LETTER I WITH MACRON, CYRILLIC SMALL LETTER I WITH MACRON +test(0x04E3, 0x04E2); // CYRILLIC SMALL LETTER I WITH MACRON, CYRILLIC CAPITAL LETTER I WITH MACRON +test(0x04E4, 0x04E5); // CYRILLIC CAPITAL LETTER I WITH DIAERESIS, CYRILLIC SMALL LETTER I WITH DIAERESIS +test(0x04E5, 0x04E4); // CYRILLIC SMALL LETTER I WITH DIAERESIS, CYRILLIC CAPITAL LETTER I WITH DIAERESIS +test(0x04E6, 0x04E7); // CYRILLIC CAPITAL LETTER O WITH DIAERESIS, CYRILLIC SMALL LETTER O WITH DIAERESIS +test(0x04E7, 0x04E6); // CYRILLIC SMALL LETTER O WITH DIAERESIS, CYRILLIC CAPITAL LETTER O WITH DIAERESIS +test(0x04E8, 0x04E9); // CYRILLIC CAPITAL LETTER BARRED O, CYRILLIC SMALL LETTER BARRED O +test(0x04E9, 0x04E8); // CYRILLIC SMALL LETTER BARRED O, CYRILLIC CAPITAL LETTER BARRED O +test(0x04EA, 0x04EB); // CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS, CYRILLIC SMALL LETTER BARRED O WITH DIAERESIS +test(0x04EB, 0x04EA); // CYRILLIC SMALL LETTER BARRED O WITH DIAERESIS, CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS +test(0x04EC, 0x04ED); // CYRILLIC CAPITAL LETTER E WITH DIAERESIS, CYRILLIC SMALL LETTER E WITH DIAERESIS +test(0x04ED, 0x04EC); // CYRILLIC SMALL LETTER E WITH DIAERESIS, CYRILLIC CAPITAL LETTER E WITH DIAERESIS +test(0x04EE, 0x04EF); // CYRILLIC CAPITAL LETTER U WITH MACRON, CYRILLIC SMALL LETTER U WITH MACRON +test(0x04EF, 0x04EE); // CYRILLIC SMALL LETTER U WITH MACRON, CYRILLIC CAPITAL LETTER U WITH MACRON +test(0x04F0, 0x04F1); // CYRILLIC CAPITAL LETTER U WITH DIAERESIS, CYRILLIC SMALL LETTER U WITH DIAERESIS +test(0x04F1, 0x04F0); // CYRILLIC SMALL LETTER U WITH DIAERESIS, CYRILLIC CAPITAL LETTER U WITH DIAERESIS +test(0x04F2, 0x04F3); // CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE, CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE +test(0x04F3, 0x04F2); // CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE, CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE +test(0x04F4, 0x04F5); // CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS, CYRILLIC SMALL LETTER CHE WITH DIAERESIS +test(0x04F5, 0x04F4); // CYRILLIC SMALL LETTER CHE WITH DIAERESIS, CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS +test(0x04F6, 0x04F7); // CYRILLIC CAPITAL LETTER GHE WITH DESCENDER, CYRILLIC SMALL LETTER GHE WITH DESCENDER +test(0x04F7, 0x04F6); // CYRILLIC SMALL LETTER GHE WITH DESCENDER, CYRILLIC CAPITAL LETTER GHE WITH DESCENDER +test(0x04F8, 0x04F9); // CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS, CYRILLIC SMALL LETTER YERU WITH DIAERESIS +test(0x04F9, 0x04F8); // CYRILLIC SMALL LETTER YERU WITH DIAERESIS, CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS +test(0x04FA, 0x04FB); // CYRILLIC CAPITAL LETTER GHE WITH STROKE AND HOOK, CYRILLIC SMALL LETTER GHE WITH STROKE AND HOOK +test(0x04FB, 0x04FA); // CYRILLIC SMALL LETTER GHE WITH STROKE AND HOOK, CYRILLIC CAPITAL LETTER GHE WITH STROKE AND HOOK +test(0x04FC, 0x04FD); // CYRILLIC CAPITAL LETTER HA WITH HOOK, CYRILLIC SMALL LETTER HA WITH HOOK +test(0x04FD, 0x04FC); // CYRILLIC SMALL LETTER HA WITH HOOK, CYRILLIC CAPITAL LETTER HA WITH HOOK +test(0x04FE, 0x04FF); // CYRILLIC CAPITAL LETTER HA WITH STROKE, CYRILLIC SMALL LETTER HA WITH STROKE +test(0x04FF, 0x04FE); // CYRILLIC SMALL LETTER HA WITH STROKE, CYRILLIC CAPITAL LETTER HA WITH STROKE +test(0x0500, 0x0501); // CYRILLIC CAPITAL LETTER KOMI DE, CYRILLIC SMALL LETTER KOMI DE +test(0x0501, 0x0500); // CYRILLIC SMALL LETTER KOMI DE, CYRILLIC CAPITAL LETTER KOMI DE +test(0x0502, 0x0503); // CYRILLIC CAPITAL LETTER KOMI DJE, CYRILLIC SMALL LETTER KOMI DJE +test(0x0503, 0x0502); // CYRILLIC SMALL LETTER KOMI DJE, CYRILLIC CAPITAL LETTER KOMI DJE +test(0x0504, 0x0505); // CYRILLIC CAPITAL LETTER KOMI ZJE, CYRILLIC SMALL LETTER KOMI ZJE +test(0x0505, 0x0504); // CYRILLIC SMALL LETTER KOMI ZJE, CYRILLIC CAPITAL LETTER KOMI ZJE +test(0x0506, 0x0507); // CYRILLIC CAPITAL LETTER KOMI DZJE, CYRILLIC SMALL LETTER KOMI DZJE +test(0x0507, 0x0506); // CYRILLIC SMALL LETTER KOMI DZJE, CYRILLIC CAPITAL LETTER KOMI DZJE +test(0x0508, 0x0509); // CYRILLIC CAPITAL LETTER KOMI LJE, CYRILLIC SMALL LETTER KOMI LJE +test(0x0509, 0x0508); // CYRILLIC SMALL LETTER KOMI LJE, CYRILLIC CAPITAL LETTER KOMI LJE +test(0x050A, 0x050B); // CYRILLIC CAPITAL LETTER KOMI NJE, CYRILLIC SMALL LETTER KOMI NJE +test(0x050B, 0x050A); // CYRILLIC SMALL LETTER KOMI NJE, CYRILLIC CAPITAL LETTER KOMI NJE +test(0x050C, 0x050D); // CYRILLIC CAPITAL LETTER KOMI SJE, CYRILLIC SMALL LETTER KOMI SJE +test(0x050D, 0x050C); // CYRILLIC SMALL LETTER KOMI SJE, CYRILLIC CAPITAL LETTER KOMI SJE +test(0x050E, 0x050F); // CYRILLIC CAPITAL LETTER KOMI TJE, CYRILLIC SMALL LETTER KOMI TJE +test(0x050F, 0x050E); // CYRILLIC SMALL LETTER KOMI TJE, CYRILLIC CAPITAL LETTER KOMI TJE +test(0x0510, 0x0511); // CYRILLIC CAPITAL LETTER REVERSED ZE, CYRILLIC SMALL LETTER REVERSED ZE +test(0x0511, 0x0510); // CYRILLIC SMALL LETTER REVERSED ZE, CYRILLIC CAPITAL LETTER REVERSED ZE +test(0x0512, 0x0513); // CYRILLIC CAPITAL LETTER EL WITH HOOK, CYRILLIC SMALL LETTER EL WITH HOOK +test(0x0513, 0x0512); // CYRILLIC SMALL LETTER EL WITH HOOK, CYRILLIC CAPITAL LETTER EL WITH HOOK +test(0x0514, 0x0515); // CYRILLIC CAPITAL LETTER LHA, CYRILLIC SMALL LETTER LHA +test(0x0515, 0x0514); // CYRILLIC SMALL LETTER LHA, CYRILLIC CAPITAL LETTER LHA +test(0x0516, 0x0517); // CYRILLIC CAPITAL LETTER RHA, CYRILLIC SMALL LETTER RHA +test(0x0517, 0x0516); // CYRILLIC SMALL LETTER RHA, CYRILLIC CAPITAL LETTER RHA +test(0x0518, 0x0519); // CYRILLIC CAPITAL LETTER YAE, CYRILLIC SMALL LETTER YAE +test(0x0519, 0x0518); // CYRILLIC SMALL LETTER YAE, CYRILLIC CAPITAL LETTER YAE +test(0x051A, 0x051B); // CYRILLIC CAPITAL LETTER QA, CYRILLIC SMALL LETTER QA +test(0x051B, 0x051A); // CYRILLIC SMALL LETTER QA, CYRILLIC CAPITAL LETTER QA +test(0x051C, 0x051D); // CYRILLIC CAPITAL LETTER WE, CYRILLIC SMALL LETTER WE +test(0x051D, 0x051C); // CYRILLIC SMALL LETTER WE, CYRILLIC CAPITAL LETTER WE +test(0x051E, 0x051F); // CYRILLIC CAPITAL LETTER ALEUT KA, CYRILLIC SMALL LETTER ALEUT KA +test(0x051F, 0x051E); // CYRILLIC SMALL LETTER ALEUT KA, CYRILLIC CAPITAL LETTER ALEUT KA +test(0x0520, 0x0521); // CYRILLIC CAPITAL LETTER EL WITH MIDDLE HOOK, CYRILLIC SMALL LETTER EL WITH MIDDLE HOOK +test(0x0521, 0x0520); // CYRILLIC SMALL LETTER EL WITH MIDDLE HOOK, CYRILLIC CAPITAL LETTER EL WITH MIDDLE HOOK +test(0x0522, 0x0523); // CYRILLIC CAPITAL LETTER EN WITH MIDDLE HOOK, CYRILLIC SMALL LETTER EN WITH MIDDLE HOOK +test(0x0523, 0x0522); // CYRILLIC SMALL LETTER EN WITH MIDDLE HOOK, CYRILLIC CAPITAL LETTER EN WITH MIDDLE HOOK +test(0x0524, 0x0525); // CYRILLIC CAPITAL LETTER PE WITH DESCENDER, CYRILLIC SMALL LETTER PE WITH DESCENDER +test(0x0525, 0x0524); // CYRILLIC SMALL LETTER PE WITH DESCENDER, CYRILLIC CAPITAL LETTER PE WITH DESCENDER +test(0x0526, 0x0527); // CYRILLIC CAPITAL LETTER SHHA WITH DESCENDER, CYRILLIC SMALL LETTER SHHA WITH DESCENDER +test(0x0527, 0x0526); // CYRILLIC SMALL LETTER SHHA WITH DESCENDER, CYRILLIC CAPITAL LETTER SHHA WITH DESCENDER +test(0x0528, 0x0529); // CYRILLIC CAPITAL LETTER EN WITH LEFT HOOK, CYRILLIC SMALL LETTER EN WITH LEFT HOOK +test(0x0529, 0x0528); // CYRILLIC SMALL LETTER EN WITH LEFT HOOK, CYRILLIC CAPITAL LETTER EN WITH LEFT HOOK +test(0x052A, 0x052B); // CYRILLIC CAPITAL LETTER DZZHE, CYRILLIC SMALL LETTER DZZHE +test(0x052B, 0x052A); // CYRILLIC SMALL LETTER DZZHE, CYRILLIC CAPITAL LETTER DZZHE +test(0x052C, 0x052D); // CYRILLIC CAPITAL LETTER DCHE, CYRILLIC SMALL LETTER DCHE +test(0x052D, 0x052C); // CYRILLIC SMALL LETTER DCHE, CYRILLIC CAPITAL LETTER DCHE +test(0x052E, 0x052F); // CYRILLIC CAPITAL LETTER EL WITH DESCENDER, CYRILLIC SMALL LETTER EL WITH DESCENDER +test(0x052F, 0x052E); // CYRILLIC SMALL LETTER EL WITH DESCENDER, CYRILLIC CAPITAL LETTER EL WITH DESCENDER +test(0x0531, 0x0561); // ARMENIAN CAPITAL LETTER AYB, ARMENIAN SMALL LETTER AYB +test(0x0532, 0x0562); // ARMENIAN CAPITAL LETTER BEN, ARMENIAN SMALL LETTER BEN +test(0x0533, 0x0563); // ARMENIAN CAPITAL LETTER GIM, ARMENIAN SMALL LETTER GIM +test(0x0534, 0x0564); // ARMENIAN CAPITAL LETTER DA, ARMENIAN SMALL LETTER DA +test(0x0535, 0x0565); // ARMENIAN CAPITAL LETTER ECH, ARMENIAN SMALL LETTER ECH +test(0x0536, 0x0566); // ARMENIAN CAPITAL LETTER ZA, ARMENIAN SMALL LETTER ZA +test(0x0537, 0x0567); // ARMENIAN CAPITAL LETTER EH, ARMENIAN SMALL LETTER EH +test(0x0538, 0x0568); // ARMENIAN CAPITAL LETTER ET, ARMENIAN SMALL LETTER ET +test(0x0539, 0x0569); // ARMENIAN CAPITAL LETTER TO, ARMENIAN SMALL LETTER TO +test(0x053A, 0x056A); // ARMENIAN CAPITAL LETTER ZHE, ARMENIAN SMALL LETTER ZHE +test(0x053B, 0x056B); // ARMENIAN CAPITAL LETTER INI, ARMENIAN SMALL LETTER INI +test(0x053C, 0x056C); // ARMENIAN CAPITAL LETTER LIWN, ARMENIAN SMALL LETTER LIWN +test(0x053D, 0x056D); // ARMENIAN CAPITAL LETTER XEH, ARMENIAN SMALL LETTER XEH +test(0x053E, 0x056E); // ARMENIAN CAPITAL LETTER CA, ARMENIAN SMALL LETTER CA +test(0x053F, 0x056F); // ARMENIAN CAPITAL LETTER KEN, ARMENIAN SMALL LETTER KEN +test(0x0540, 0x0570); // ARMENIAN CAPITAL LETTER HO, ARMENIAN SMALL LETTER HO +test(0x0541, 0x0571); // ARMENIAN CAPITAL LETTER JA, ARMENIAN SMALL LETTER JA +test(0x0542, 0x0572); // ARMENIAN CAPITAL LETTER GHAD (ARMENIAN CAPITAL LETTER LAD), ARMENIAN SMALL LETTER GHAD (ARMENIAN SMALL LETTER LAD) +test(0x0543, 0x0573); // ARMENIAN CAPITAL LETTER CHEH, ARMENIAN SMALL LETTER CHEH +test(0x0544, 0x0574); // ARMENIAN CAPITAL LETTER MEN, ARMENIAN SMALL LETTER MEN +test(0x0545, 0x0575); // ARMENIAN CAPITAL LETTER YI, ARMENIAN SMALL LETTER YI +test(0x0546, 0x0576); // ARMENIAN CAPITAL LETTER NOW, ARMENIAN SMALL LETTER NOW +test(0x0547, 0x0577); // ARMENIAN CAPITAL LETTER SHA, ARMENIAN SMALL LETTER SHA +test(0x0548, 0x0578); // ARMENIAN CAPITAL LETTER VO, ARMENIAN SMALL LETTER VO +test(0x0549, 0x0579); // ARMENIAN CAPITAL LETTER CHA, ARMENIAN SMALL LETTER CHA +test(0x054A, 0x057A); // ARMENIAN CAPITAL LETTER PEH, ARMENIAN SMALL LETTER PEH +test(0x054B, 0x057B); // ARMENIAN CAPITAL LETTER JHEH, ARMENIAN SMALL LETTER JHEH +test(0x054C, 0x057C); // ARMENIAN CAPITAL LETTER RA, ARMENIAN SMALL LETTER RA +test(0x054D, 0x057D); // ARMENIAN CAPITAL LETTER SEH, ARMENIAN SMALL LETTER SEH +test(0x054E, 0x057E); // ARMENIAN CAPITAL LETTER VEW, ARMENIAN SMALL LETTER VEW +test(0x054F, 0x057F); // ARMENIAN CAPITAL LETTER TIWN, ARMENIAN SMALL LETTER TIWN +test(0x0550, 0x0580); // ARMENIAN CAPITAL LETTER REH, ARMENIAN SMALL LETTER REH +test(0x0551, 0x0581); // ARMENIAN CAPITAL LETTER CO, ARMENIAN SMALL LETTER CO +test(0x0552, 0x0582); // ARMENIAN CAPITAL LETTER YIWN, ARMENIAN SMALL LETTER YIWN +test(0x0553, 0x0583); // ARMENIAN CAPITAL LETTER PIWR, ARMENIAN SMALL LETTER PIWR +test(0x0554, 0x0584); // ARMENIAN CAPITAL LETTER KEH, ARMENIAN SMALL LETTER KEH +test(0x0555, 0x0585); // ARMENIAN CAPITAL LETTER OH, ARMENIAN SMALL LETTER OH +test(0x0556, 0x0586); // ARMENIAN CAPITAL LETTER FEH, ARMENIAN SMALL LETTER FEH +test(0x0561, 0x0531); // ARMENIAN SMALL LETTER AYB, ARMENIAN CAPITAL LETTER AYB +test(0x0562, 0x0532); // ARMENIAN SMALL LETTER BEN, ARMENIAN CAPITAL LETTER BEN +test(0x0563, 0x0533); // ARMENIAN SMALL LETTER GIM, ARMENIAN CAPITAL LETTER GIM +test(0x0564, 0x0534); // ARMENIAN SMALL LETTER DA, ARMENIAN CAPITAL LETTER DA +test(0x0565, 0x0535); // ARMENIAN SMALL LETTER ECH, ARMENIAN CAPITAL LETTER ECH +test(0x0566, 0x0536); // ARMENIAN SMALL LETTER ZA, ARMENIAN CAPITAL LETTER ZA +test(0x0567, 0x0537); // ARMENIAN SMALL LETTER EH, ARMENIAN CAPITAL LETTER EH +test(0x0568, 0x0538); // ARMENIAN SMALL LETTER ET, ARMENIAN CAPITAL LETTER ET +test(0x0569, 0x0539); // ARMENIAN SMALL LETTER TO, ARMENIAN CAPITAL LETTER TO +test(0x056A, 0x053A); // ARMENIAN SMALL LETTER ZHE, ARMENIAN CAPITAL LETTER ZHE +test(0x056B, 0x053B); // ARMENIAN SMALL LETTER INI, ARMENIAN CAPITAL LETTER INI +test(0x056C, 0x053C); // ARMENIAN SMALL LETTER LIWN, ARMENIAN CAPITAL LETTER LIWN +test(0x056D, 0x053D); // ARMENIAN SMALL LETTER XEH, ARMENIAN CAPITAL LETTER XEH +test(0x056E, 0x053E); // ARMENIAN SMALL LETTER CA, ARMENIAN CAPITAL LETTER CA +test(0x056F, 0x053F); // ARMENIAN SMALL LETTER KEN, ARMENIAN CAPITAL LETTER KEN +test(0x0570, 0x0540); // ARMENIAN SMALL LETTER HO, ARMENIAN CAPITAL LETTER HO +test(0x0571, 0x0541); // ARMENIAN SMALL LETTER JA, ARMENIAN CAPITAL LETTER JA +test(0x0572, 0x0542); // ARMENIAN SMALL LETTER GHAD (ARMENIAN SMALL LETTER LAD), ARMENIAN CAPITAL LETTER GHAD (ARMENIAN CAPITAL LETTER LAD) +test(0x0573, 0x0543); // ARMENIAN SMALL LETTER CHEH, ARMENIAN CAPITAL LETTER CHEH +test(0x0574, 0x0544); // ARMENIAN SMALL LETTER MEN, ARMENIAN CAPITAL LETTER MEN +test(0x0575, 0x0545); // ARMENIAN SMALL LETTER YI, ARMENIAN CAPITAL LETTER YI +test(0x0576, 0x0546); // ARMENIAN SMALL LETTER NOW, ARMENIAN CAPITAL LETTER NOW +test(0x0577, 0x0547); // ARMENIAN SMALL LETTER SHA, ARMENIAN CAPITAL LETTER SHA +test(0x0578, 0x0548); // ARMENIAN SMALL LETTER VO, ARMENIAN CAPITAL LETTER VO +test(0x0579, 0x0549); // ARMENIAN SMALL LETTER CHA, ARMENIAN CAPITAL LETTER CHA +test(0x057A, 0x054A); // ARMENIAN SMALL LETTER PEH, ARMENIAN CAPITAL LETTER PEH +test(0x057B, 0x054B); // ARMENIAN SMALL LETTER JHEH, ARMENIAN CAPITAL LETTER JHEH +test(0x057C, 0x054C); // ARMENIAN SMALL LETTER RA, ARMENIAN CAPITAL LETTER RA +test(0x057D, 0x054D); // ARMENIAN SMALL LETTER SEH, ARMENIAN CAPITAL LETTER SEH +test(0x057E, 0x054E); // ARMENIAN SMALL LETTER VEW, ARMENIAN CAPITAL LETTER VEW +test(0x057F, 0x054F); // ARMENIAN SMALL LETTER TIWN, ARMENIAN CAPITAL LETTER TIWN +test(0x0580, 0x0550); // ARMENIAN SMALL LETTER REH, ARMENIAN CAPITAL LETTER REH +test(0x0581, 0x0551); // ARMENIAN SMALL LETTER CO, ARMENIAN CAPITAL LETTER CO +test(0x0582, 0x0552); // ARMENIAN SMALL LETTER YIWN, ARMENIAN CAPITAL LETTER YIWN +test(0x0583, 0x0553); // ARMENIAN SMALL LETTER PIWR, ARMENIAN CAPITAL LETTER PIWR +test(0x0584, 0x0554); // ARMENIAN SMALL LETTER KEH, ARMENIAN CAPITAL LETTER KEH +test(0x0585, 0x0555); // ARMENIAN SMALL LETTER OH, ARMENIAN CAPITAL LETTER OH +test(0x0586, 0x0556); // ARMENIAN SMALL LETTER FEH, ARMENIAN CAPITAL LETTER FEH +test(0x10A0, 0x2D00); // GEORGIAN CAPITAL LETTER AN, GEORGIAN SMALL LETTER AN +test(0x10A1, 0x2D01); // GEORGIAN CAPITAL LETTER BAN, GEORGIAN SMALL LETTER BAN +test(0x10A2, 0x2D02); // GEORGIAN CAPITAL LETTER GAN, GEORGIAN SMALL LETTER GAN +test(0x10A3, 0x2D03); // GEORGIAN CAPITAL LETTER DON, GEORGIAN SMALL LETTER DON +test(0x10A4, 0x2D04); // GEORGIAN CAPITAL LETTER EN, GEORGIAN SMALL LETTER EN +test(0x10A5, 0x2D05); // GEORGIAN CAPITAL LETTER VIN, GEORGIAN SMALL LETTER VIN +test(0x10A6, 0x2D06); // GEORGIAN CAPITAL LETTER ZEN, GEORGIAN SMALL LETTER ZEN +test(0x10A7, 0x2D07); // GEORGIAN CAPITAL LETTER TAN, GEORGIAN SMALL LETTER TAN +test(0x10A8, 0x2D08); // GEORGIAN CAPITAL LETTER IN, GEORGIAN SMALL LETTER IN +test(0x10A9, 0x2D09); // GEORGIAN CAPITAL LETTER KAN, GEORGIAN SMALL LETTER KAN +test(0x10AA, 0x2D0A); // GEORGIAN CAPITAL LETTER LAS, GEORGIAN SMALL LETTER LAS +test(0x10AB, 0x2D0B); // GEORGIAN CAPITAL LETTER MAN, GEORGIAN SMALL LETTER MAN +test(0x10AC, 0x2D0C); // GEORGIAN CAPITAL LETTER NAR, GEORGIAN SMALL LETTER NAR +test(0x10AD, 0x2D0D); // GEORGIAN CAPITAL LETTER ON, GEORGIAN SMALL LETTER ON +test(0x10AE, 0x2D0E); // GEORGIAN CAPITAL LETTER PAR, GEORGIAN SMALL LETTER PAR +test(0x10AF, 0x2D0F); // GEORGIAN CAPITAL LETTER ZHAR, GEORGIAN SMALL LETTER ZHAR +test(0x10B0, 0x2D10); // GEORGIAN CAPITAL LETTER RAE, GEORGIAN SMALL LETTER RAE +test(0x10B1, 0x2D11); // GEORGIAN CAPITAL LETTER SAN, GEORGIAN SMALL LETTER SAN +test(0x10B2, 0x2D12); // GEORGIAN CAPITAL LETTER TAR, GEORGIAN SMALL LETTER TAR +test(0x10B3, 0x2D13); // GEORGIAN CAPITAL LETTER UN, GEORGIAN SMALL LETTER UN +test(0x10B4, 0x2D14); // GEORGIAN CAPITAL LETTER PHAR, GEORGIAN SMALL LETTER PHAR +test(0x10B5, 0x2D15); // GEORGIAN CAPITAL LETTER KHAR, GEORGIAN SMALL LETTER KHAR +test(0x10B6, 0x2D16); // GEORGIAN CAPITAL LETTER GHAN, GEORGIAN SMALL LETTER GHAN +test(0x10B7, 0x2D17); // GEORGIAN CAPITAL LETTER QAR, GEORGIAN SMALL LETTER QAR +test(0x10B8, 0x2D18); // GEORGIAN CAPITAL LETTER SHIN, GEORGIAN SMALL LETTER SHIN +test(0x10B9, 0x2D19); // GEORGIAN CAPITAL LETTER CHIN, GEORGIAN SMALL LETTER CHIN +test(0x10BA, 0x2D1A); // GEORGIAN CAPITAL LETTER CAN, GEORGIAN SMALL LETTER CAN +test(0x10BB, 0x2D1B); // GEORGIAN CAPITAL LETTER JIL, GEORGIAN SMALL LETTER JIL +test(0x10BC, 0x2D1C); // GEORGIAN CAPITAL LETTER CIL, GEORGIAN SMALL LETTER CIL +test(0x10BD, 0x2D1D); // GEORGIAN CAPITAL LETTER CHAR, GEORGIAN SMALL LETTER CHAR +test(0x10BE, 0x2D1E); // GEORGIAN CAPITAL LETTER XAN, GEORGIAN SMALL LETTER XAN +test(0x10BF, 0x2D1F); // GEORGIAN CAPITAL LETTER JHAN, GEORGIAN SMALL LETTER JHAN +test(0x10C0, 0x2D20); // GEORGIAN CAPITAL LETTER HAE, GEORGIAN SMALL LETTER HAE +test(0x10C1, 0x2D21); // GEORGIAN CAPITAL LETTER HE, GEORGIAN SMALL LETTER HE +test(0x10C2, 0x2D22); // GEORGIAN CAPITAL LETTER HIE, GEORGIAN SMALL LETTER HIE +test(0x10C3, 0x2D23); // GEORGIAN CAPITAL LETTER WE, GEORGIAN SMALL LETTER WE +test(0x10C4, 0x2D24); // GEORGIAN CAPITAL LETTER HAR, GEORGIAN SMALL LETTER HAR +test(0x10C5, 0x2D25); // GEORGIAN CAPITAL LETTER HOE, GEORGIAN SMALL LETTER HOE +test(0x10C7, 0x2D27); // GEORGIAN CAPITAL LETTER YN, GEORGIAN SMALL LETTER YN +test(0x10CD, 0x2D2D); // GEORGIAN CAPITAL LETTER AEN, GEORGIAN SMALL LETTER AEN +test(0x10D0, 0x1C90); // GEORGIAN LETTER AN (GEORGIAN SMALL LETTER AN), GEORGIAN MTAVRULI CAPITAL LETTER AN +test(0x10D1, 0x1C91); // GEORGIAN LETTER BAN (GEORGIAN SMALL LETTER BAN), GEORGIAN MTAVRULI CAPITAL LETTER BAN +test(0x10D2, 0x1C92); // GEORGIAN LETTER GAN (GEORGIAN SMALL LETTER GAN), GEORGIAN MTAVRULI CAPITAL LETTER GAN +test(0x10D3, 0x1C93); // GEORGIAN LETTER DON (GEORGIAN SMALL LETTER DON), GEORGIAN MTAVRULI CAPITAL LETTER DON +test(0x10D4, 0x1C94); // GEORGIAN LETTER EN (GEORGIAN SMALL LETTER EN), GEORGIAN MTAVRULI CAPITAL LETTER EN +test(0x10D5, 0x1C95); // GEORGIAN LETTER VIN (GEORGIAN SMALL LETTER VIN), GEORGIAN MTAVRULI CAPITAL LETTER VIN +test(0x10D6, 0x1C96); // GEORGIAN LETTER ZEN (GEORGIAN SMALL LETTER ZEN), GEORGIAN MTAVRULI CAPITAL LETTER ZEN +test(0x10D7, 0x1C97); // GEORGIAN LETTER TAN (GEORGIAN SMALL LETTER TAN), GEORGIAN MTAVRULI CAPITAL LETTER TAN +test(0x10D8, 0x1C98); // GEORGIAN LETTER IN (GEORGIAN SMALL LETTER IN), GEORGIAN MTAVRULI CAPITAL LETTER IN +test(0x10D9, 0x1C99); // GEORGIAN LETTER KAN (GEORGIAN SMALL LETTER KAN), GEORGIAN MTAVRULI CAPITAL LETTER KAN +test(0x10DA, 0x1C9A); // GEORGIAN LETTER LAS (GEORGIAN SMALL LETTER LAS), GEORGIAN MTAVRULI CAPITAL LETTER LAS +test(0x10DB, 0x1C9B); // GEORGIAN LETTER MAN (GEORGIAN SMALL LETTER MAN), GEORGIAN MTAVRULI CAPITAL LETTER MAN +test(0x10DC, 0x1C9C); // GEORGIAN LETTER NAR (GEORGIAN SMALL LETTER NAR), GEORGIAN MTAVRULI CAPITAL LETTER NAR +test(0x10DD, 0x1C9D); // GEORGIAN LETTER ON (GEORGIAN SMALL LETTER ON), GEORGIAN MTAVRULI CAPITAL LETTER ON +test(0x10DE, 0x1C9E); // GEORGIAN LETTER PAR (GEORGIAN SMALL LETTER PAR), GEORGIAN MTAVRULI CAPITAL LETTER PAR +test(0x10DF, 0x1C9F); // GEORGIAN LETTER ZHAR (GEORGIAN SMALL LETTER ZHAR), GEORGIAN MTAVRULI CAPITAL LETTER ZHAR +test(0x10E0, 0x1CA0); // GEORGIAN LETTER RAE (GEORGIAN SMALL LETTER RAE), GEORGIAN MTAVRULI CAPITAL LETTER RAE +test(0x10E1, 0x1CA1); // GEORGIAN LETTER SAN (GEORGIAN SMALL LETTER SAN), GEORGIAN MTAVRULI CAPITAL LETTER SAN +test(0x10E2, 0x1CA2); // GEORGIAN LETTER TAR (GEORGIAN SMALL LETTER TAR), GEORGIAN MTAVRULI CAPITAL LETTER TAR +test(0x10E3, 0x1CA3); // GEORGIAN LETTER UN (GEORGIAN SMALL LETTER UN), GEORGIAN MTAVRULI CAPITAL LETTER UN +test(0x10E4, 0x1CA4); // GEORGIAN LETTER PHAR (GEORGIAN SMALL LETTER PHAR), GEORGIAN MTAVRULI CAPITAL LETTER PHAR +test(0x10E5, 0x1CA5); // GEORGIAN LETTER KHAR (GEORGIAN SMALL LETTER KHAR), GEORGIAN MTAVRULI CAPITAL LETTER KHAR +test(0x10E6, 0x1CA6); // GEORGIAN LETTER GHAN (GEORGIAN SMALL LETTER GHAN), GEORGIAN MTAVRULI CAPITAL LETTER GHAN +test(0x10E7, 0x1CA7); // GEORGIAN LETTER QAR (GEORGIAN SMALL LETTER QAR), GEORGIAN MTAVRULI CAPITAL LETTER QAR +test(0x10E8, 0x1CA8); // GEORGIAN LETTER SHIN (GEORGIAN SMALL LETTER SHIN), GEORGIAN MTAVRULI CAPITAL LETTER SHIN +test(0x10E9, 0x1CA9); // GEORGIAN LETTER CHIN (GEORGIAN SMALL LETTER CHIN), GEORGIAN MTAVRULI CAPITAL LETTER CHIN +test(0x10EA, 0x1CAA); // GEORGIAN LETTER CAN (GEORGIAN SMALL LETTER CAN), GEORGIAN MTAVRULI CAPITAL LETTER CAN +test(0x10EB, 0x1CAB); // GEORGIAN LETTER JIL (GEORGIAN SMALL LETTER JIL), GEORGIAN MTAVRULI CAPITAL LETTER JIL +test(0x10EC, 0x1CAC); // GEORGIAN LETTER CIL (GEORGIAN SMALL LETTER CIL), GEORGIAN MTAVRULI CAPITAL LETTER CIL +test(0x10ED, 0x1CAD); // GEORGIAN LETTER CHAR (GEORGIAN SMALL LETTER CHAR), GEORGIAN MTAVRULI CAPITAL LETTER CHAR +test(0x10EE, 0x1CAE); // GEORGIAN LETTER XAN (GEORGIAN SMALL LETTER XAN), GEORGIAN MTAVRULI CAPITAL LETTER XAN +test(0x10EF, 0x1CAF); // GEORGIAN LETTER JHAN (GEORGIAN SMALL LETTER JHAN), GEORGIAN MTAVRULI CAPITAL LETTER JHAN +test(0x10F0, 0x1CB0); // GEORGIAN LETTER HAE (GEORGIAN SMALL LETTER HAE), GEORGIAN MTAVRULI CAPITAL LETTER HAE +test(0x10F1, 0x1CB1); // GEORGIAN LETTER HE (GEORGIAN SMALL LETTER HE), GEORGIAN MTAVRULI CAPITAL LETTER HE +test(0x10F2, 0x1CB2); // GEORGIAN LETTER HIE (GEORGIAN SMALL LETTER HIE), GEORGIAN MTAVRULI CAPITAL LETTER HIE +test(0x10F3, 0x1CB3); // GEORGIAN LETTER WE (GEORGIAN SMALL LETTER WE), GEORGIAN MTAVRULI CAPITAL LETTER WE +test(0x10F4, 0x1CB4); // GEORGIAN LETTER HAR (GEORGIAN SMALL LETTER HAR), GEORGIAN MTAVRULI CAPITAL LETTER HAR +test(0x10F5, 0x1CB5); // GEORGIAN LETTER HOE (GEORGIAN SMALL LETTER HOE), GEORGIAN MTAVRULI CAPITAL LETTER HOE +test(0x10F6, 0x1CB6); // GEORGIAN LETTER FI (GEORGIAN SMALL LETTER FI), GEORGIAN MTAVRULI CAPITAL LETTER FI +test(0x10F7, 0x1CB7); // GEORGIAN LETTER YN, GEORGIAN MTAVRULI CAPITAL LETTER YN +test(0x10F8, 0x1CB8); // GEORGIAN LETTER ELIFI, GEORGIAN MTAVRULI CAPITAL LETTER ELIFI +test(0x10F9, 0x1CB9); // GEORGIAN LETTER TURNED GAN, GEORGIAN MTAVRULI CAPITAL LETTER TURNED GAN +test(0x10FA, 0x1CBA); // GEORGIAN LETTER AIN, GEORGIAN MTAVRULI CAPITAL LETTER AIN +test(0x10FD, 0x1CBD); // GEORGIAN LETTER AEN, GEORGIAN MTAVRULI CAPITAL LETTER AEN +test(0x10FE, 0x1CBE); // GEORGIAN LETTER HARD SIGN, GEORGIAN MTAVRULI CAPITAL LETTER HARD SIGN +test(0x10FF, 0x1CBF); // GEORGIAN LETTER LABIAL SIGN, GEORGIAN MTAVRULI CAPITAL LETTER LABIAL SIGN +test(0x13A0, 0xAB70); // CHEROKEE LETTER A, CHEROKEE SMALL LETTER A +test(0x13A1, 0xAB71); // CHEROKEE LETTER E, CHEROKEE SMALL LETTER E +test(0x13A2, 0xAB72); // CHEROKEE LETTER I, CHEROKEE SMALL LETTER I +test(0x13A3, 0xAB73); // CHEROKEE LETTER O, CHEROKEE SMALL LETTER O +test(0x13A4, 0xAB74); // CHEROKEE LETTER U, CHEROKEE SMALL LETTER U +test(0x13A5, 0xAB75); // CHEROKEE LETTER V, CHEROKEE SMALL LETTER V +test(0x13A6, 0xAB76); // CHEROKEE LETTER GA, CHEROKEE SMALL LETTER GA +test(0x13A7, 0xAB77); // CHEROKEE LETTER KA, CHEROKEE SMALL LETTER KA +test(0x13A8, 0xAB78); // CHEROKEE LETTER GE, CHEROKEE SMALL LETTER GE +test(0x13A9, 0xAB79); // CHEROKEE LETTER GI, CHEROKEE SMALL LETTER GI +test(0x13AA, 0xAB7A); // CHEROKEE LETTER GO, CHEROKEE SMALL LETTER GO +test(0x13AB, 0xAB7B); // CHEROKEE LETTER GU, CHEROKEE SMALL LETTER GU +test(0x13AC, 0xAB7C); // CHEROKEE LETTER GV, CHEROKEE SMALL LETTER GV +test(0x13AD, 0xAB7D); // CHEROKEE LETTER HA, CHEROKEE SMALL LETTER HA +test(0x13AE, 0xAB7E); // CHEROKEE LETTER HE, CHEROKEE SMALL LETTER HE +test(0x13AF, 0xAB7F); // CHEROKEE LETTER HI, CHEROKEE SMALL LETTER HI +test(0x13B0, 0xAB80); // CHEROKEE LETTER HO, CHEROKEE SMALL LETTER HO +test(0x13B1, 0xAB81); // CHEROKEE LETTER HU, CHEROKEE SMALL LETTER HU +test(0x13B2, 0xAB82); // CHEROKEE LETTER HV, CHEROKEE SMALL LETTER HV +test(0x13B3, 0xAB83); // CHEROKEE LETTER LA, CHEROKEE SMALL LETTER LA +test(0x13B4, 0xAB84); // CHEROKEE LETTER LE, CHEROKEE SMALL LETTER LE +test(0x13B5, 0xAB85); // CHEROKEE LETTER LI, CHEROKEE SMALL LETTER LI +test(0x13B6, 0xAB86); // CHEROKEE LETTER LO, CHEROKEE SMALL LETTER LO +test(0x13B7, 0xAB87); // CHEROKEE LETTER LU, CHEROKEE SMALL LETTER LU +test(0x13B8, 0xAB88); // CHEROKEE LETTER LV, CHEROKEE SMALL LETTER LV +test(0x13B9, 0xAB89); // CHEROKEE LETTER MA, CHEROKEE SMALL LETTER MA +test(0x13BA, 0xAB8A); // CHEROKEE LETTER ME, CHEROKEE SMALL LETTER ME +test(0x13BB, 0xAB8B); // CHEROKEE LETTER MI, CHEROKEE SMALL LETTER MI +test(0x13BC, 0xAB8C); // CHEROKEE LETTER MO, CHEROKEE SMALL LETTER MO +test(0x13BD, 0xAB8D); // CHEROKEE LETTER MU, CHEROKEE SMALL LETTER MU +test(0x13BE, 0xAB8E); // CHEROKEE LETTER NA, CHEROKEE SMALL LETTER NA +test(0x13BF, 0xAB8F); // CHEROKEE LETTER HNA, CHEROKEE SMALL LETTER HNA +test(0x13C0, 0xAB90); // CHEROKEE LETTER NAH, CHEROKEE SMALL LETTER NAH +test(0x13C1, 0xAB91); // CHEROKEE LETTER NE, CHEROKEE SMALL LETTER NE +test(0x13C2, 0xAB92); // CHEROKEE LETTER NI, CHEROKEE SMALL LETTER NI +test(0x13C3, 0xAB93); // CHEROKEE LETTER NO, CHEROKEE SMALL LETTER NO +test(0x13C4, 0xAB94); // CHEROKEE LETTER NU, CHEROKEE SMALL LETTER NU +test(0x13C5, 0xAB95); // CHEROKEE LETTER NV, CHEROKEE SMALL LETTER NV +test(0x13C6, 0xAB96); // CHEROKEE LETTER QUA, CHEROKEE SMALL LETTER QUA +test(0x13C7, 0xAB97); // CHEROKEE LETTER QUE, CHEROKEE SMALL LETTER QUE +test(0x13C8, 0xAB98); // CHEROKEE LETTER QUI, CHEROKEE SMALL LETTER QUI +test(0x13C9, 0xAB99); // CHEROKEE LETTER QUO, CHEROKEE SMALL LETTER QUO +test(0x13CA, 0xAB9A); // CHEROKEE LETTER QUU, CHEROKEE SMALL LETTER QUU +test(0x13CB, 0xAB9B); // CHEROKEE LETTER QUV, CHEROKEE SMALL LETTER QUV +test(0x13CC, 0xAB9C); // CHEROKEE LETTER SA, CHEROKEE SMALL LETTER SA +test(0x13CD, 0xAB9D); // CHEROKEE LETTER S, CHEROKEE SMALL LETTER S +test(0x13CE, 0xAB9E); // CHEROKEE LETTER SE, CHEROKEE SMALL LETTER SE +test(0x13CF, 0xAB9F); // CHEROKEE LETTER SI, CHEROKEE SMALL LETTER SI +test(0x13D0, 0xABA0); // CHEROKEE LETTER SO, CHEROKEE SMALL LETTER SO +test(0x13D1, 0xABA1); // CHEROKEE LETTER SU, CHEROKEE SMALL LETTER SU +test(0x13D2, 0xABA2); // CHEROKEE LETTER SV, CHEROKEE SMALL LETTER SV +test(0x13D3, 0xABA3); // CHEROKEE LETTER DA, CHEROKEE SMALL LETTER DA +test(0x13D4, 0xABA4); // CHEROKEE LETTER TA, CHEROKEE SMALL LETTER TA +test(0x13D5, 0xABA5); // CHEROKEE LETTER DE, CHEROKEE SMALL LETTER DE +test(0x13D6, 0xABA6); // CHEROKEE LETTER TE, CHEROKEE SMALL LETTER TE +test(0x13D7, 0xABA7); // CHEROKEE LETTER DI, CHEROKEE SMALL LETTER DI +test(0x13D8, 0xABA8); // CHEROKEE LETTER TI, CHEROKEE SMALL LETTER TI +test(0x13D9, 0xABA9); // CHEROKEE LETTER DO, CHEROKEE SMALL LETTER DO +test(0x13DA, 0xABAA); // CHEROKEE LETTER DU, CHEROKEE SMALL LETTER DU +test(0x13DB, 0xABAB); // CHEROKEE LETTER DV, CHEROKEE SMALL LETTER DV +test(0x13DC, 0xABAC); // CHEROKEE LETTER DLA, CHEROKEE SMALL LETTER DLA +test(0x13DD, 0xABAD); // CHEROKEE LETTER TLA, CHEROKEE SMALL LETTER TLA +test(0x13DE, 0xABAE); // CHEROKEE LETTER TLE, CHEROKEE SMALL LETTER TLE +test(0x13DF, 0xABAF); // CHEROKEE LETTER TLI, CHEROKEE SMALL LETTER TLI +test(0x13E0, 0xABB0); // CHEROKEE LETTER TLO, CHEROKEE SMALL LETTER TLO +test(0x13E1, 0xABB1); // CHEROKEE LETTER TLU, CHEROKEE SMALL LETTER TLU +test(0x13E2, 0xABB2); // CHEROKEE LETTER TLV, CHEROKEE SMALL LETTER TLV +test(0x13E3, 0xABB3); // CHEROKEE LETTER TSA, CHEROKEE SMALL LETTER TSA +test(0x13E4, 0xABB4); // CHEROKEE LETTER TSE, CHEROKEE SMALL LETTER TSE +test(0x13E5, 0xABB5); // CHEROKEE LETTER TSI, CHEROKEE SMALL LETTER TSI +test(0x13E6, 0xABB6); // CHEROKEE LETTER TSO, CHEROKEE SMALL LETTER TSO +test(0x13E7, 0xABB7); // CHEROKEE LETTER TSU, CHEROKEE SMALL LETTER TSU +test(0x13E8, 0xABB8); // CHEROKEE LETTER TSV, CHEROKEE SMALL LETTER TSV +test(0x13E9, 0xABB9); // CHEROKEE LETTER WA, CHEROKEE SMALL LETTER WA +test(0x13EA, 0xABBA); // CHEROKEE LETTER WE, CHEROKEE SMALL LETTER WE +test(0x13EB, 0xABBB); // CHEROKEE LETTER WI, CHEROKEE SMALL LETTER WI +test(0x13EC, 0xABBC); // CHEROKEE LETTER WO, CHEROKEE SMALL LETTER WO +test(0x13ED, 0xABBD); // CHEROKEE LETTER WU, CHEROKEE SMALL LETTER WU +test(0x13EE, 0xABBE); // CHEROKEE LETTER WV, CHEROKEE SMALL LETTER WV +test(0x13EF, 0xABBF); // CHEROKEE LETTER YA, CHEROKEE SMALL LETTER YA +test(0x13F0, 0x13F8); // CHEROKEE LETTER YE, CHEROKEE SMALL LETTER YE +test(0x13F1, 0x13F9); // CHEROKEE LETTER YI, CHEROKEE SMALL LETTER YI +test(0x13F2, 0x13FA); // CHEROKEE LETTER YO, CHEROKEE SMALL LETTER YO +test(0x13F3, 0x13FB); // CHEROKEE LETTER YU, CHEROKEE SMALL LETTER YU +test(0x13F4, 0x13FC); // CHEROKEE LETTER YV, CHEROKEE SMALL LETTER YV +test(0x13F5, 0x13FD); // CHEROKEE LETTER MV, CHEROKEE SMALL LETTER MV +test(0x13F8, 0x13F0); // CHEROKEE SMALL LETTER YE, CHEROKEE LETTER YE +test(0x13F9, 0x13F1); // CHEROKEE SMALL LETTER YI, CHEROKEE LETTER YI +test(0x13FA, 0x13F2); // CHEROKEE SMALL LETTER YO, CHEROKEE LETTER YO +test(0x13FB, 0x13F3); // CHEROKEE SMALL LETTER YU, CHEROKEE LETTER YU +test(0x13FC, 0x13F4); // CHEROKEE SMALL LETTER YV, CHEROKEE LETTER YV +test(0x13FD, 0x13F5); // CHEROKEE SMALL LETTER MV, CHEROKEE LETTER MV +test(0x1C80, 0x0432, 0x0412); // CYRILLIC SMALL LETTER ROUNDED VE, CYRILLIC SMALL LETTER VE, CYRILLIC CAPITAL LETTER VE +test(0x1C81, 0x0434, 0x0414); // CYRILLIC SMALL LETTER LONG-LEGGED DE, CYRILLIC SMALL LETTER DE, CYRILLIC CAPITAL LETTER DE +test(0x1C82, 0x043E, 0x041E); // CYRILLIC SMALL LETTER NARROW O, CYRILLIC SMALL LETTER O, CYRILLIC CAPITAL LETTER O +test(0x1C83, 0x0441, 0x0421); // CYRILLIC SMALL LETTER WIDE ES, CYRILLIC SMALL LETTER ES, CYRILLIC CAPITAL LETTER ES +test(0x1C84, 0x0442, 0x0422, 0x1C85); // CYRILLIC SMALL LETTER TALL TE, CYRILLIC SMALL LETTER TE, CYRILLIC CAPITAL LETTER TE, CYRILLIC SMALL LETTER THREE-LEGGED TE +test(0x1C85, 0x0442, 0x0422, 0x1C84); // CYRILLIC SMALL LETTER THREE-LEGGED TE, CYRILLIC SMALL LETTER TE, CYRILLIC CAPITAL LETTER TE, CYRILLIC SMALL LETTER TALL TE +test(0x1C86, 0x044A, 0x042A); // CYRILLIC SMALL LETTER TALL HARD SIGN, CYRILLIC SMALL LETTER HARD SIGN, CYRILLIC CAPITAL LETTER HARD SIGN +test(0x1C87, 0x0463, 0x0462); // CYRILLIC SMALL LETTER TALL YAT, CYRILLIC SMALL LETTER YAT, CYRILLIC CAPITAL LETTER YAT +test(0x1C88, 0xA64B, 0xA64A); // CYRILLIC SMALL LETTER UNBLENDED UK, CYRILLIC SMALL LETTER MONOGRAPH UK, CYRILLIC CAPITAL LETTER MONOGRAPH UK +test(0x1C90, 0x10D0); // GEORGIAN MTAVRULI CAPITAL LETTER AN, GEORGIAN LETTER AN (GEORGIAN SMALL LETTER AN) +test(0x1C91, 0x10D1); // GEORGIAN MTAVRULI CAPITAL LETTER BAN, GEORGIAN LETTER BAN (GEORGIAN SMALL LETTER BAN) +test(0x1C92, 0x10D2); // GEORGIAN MTAVRULI CAPITAL LETTER GAN, GEORGIAN LETTER GAN (GEORGIAN SMALL LETTER GAN) +test(0x1C93, 0x10D3); // GEORGIAN MTAVRULI CAPITAL LETTER DON, GEORGIAN LETTER DON (GEORGIAN SMALL LETTER DON) +test(0x1C94, 0x10D4); // GEORGIAN MTAVRULI CAPITAL LETTER EN, GEORGIAN LETTER EN (GEORGIAN SMALL LETTER EN) +test(0x1C95, 0x10D5); // GEORGIAN MTAVRULI CAPITAL LETTER VIN, GEORGIAN LETTER VIN (GEORGIAN SMALL LETTER VIN) +test(0x1C96, 0x10D6); // GEORGIAN MTAVRULI CAPITAL LETTER ZEN, GEORGIAN LETTER ZEN (GEORGIAN SMALL LETTER ZEN) +test(0x1C97, 0x10D7); // GEORGIAN MTAVRULI CAPITAL LETTER TAN, GEORGIAN LETTER TAN (GEORGIAN SMALL LETTER TAN) +test(0x1C98, 0x10D8); // GEORGIAN MTAVRULI CAPITAL LETTER IN, GEORGIAN LETTER IN (GEORGIAN SMALL LETTER IN) +test(0x1C99, 0x10D9); // GEORGIAN MTAVRULI CAPITAL LETTER KAN, GEORGIAN LETTER KAN (GEORGIAN SMALL LETTER KAN) +test(0x1C9A, 0x10DA); // GEORGIAN MTAVRULI CAPITAL LETTER LAS, GEORGIAN LETTER LAS (GEORGIAN SMALL LETTER LAS) +test(0x1C9B, 0x10DB); // GEORGIAN MTAVRULI CAPITAL LETTER MAN, GEORGIAN LETTER MAN (GEORGIAN SMALL LETTER MAN) +test(0x1C9C, 0x10DC); // GEORGIAN MTAVRULI CAPITAL LETTER NAR, GEORGIAN LETTER NAR (GEORGIAN SMALL LETTER NAR) +test(0x1C9D, 0x10DD); // GEORGIAN MTAVRULI CAPITAL LETTER ON, GEORGIAN LETTER ON (GEORGIAN SMALL LETTER ON) +test(0x1C9E, 0x10DE); // GEORGIAN MTAVRULI CAPITAL LETTER PAR, GEORGIAN LETTER PAR (GEORGIAN SMALL LETTER PAR) +test(0x1C9F, 0x10DF); // GEORGIAN MTAVRULI CAPITAL LETTER ZHAR, GEORGIAN LETTER ZHAR (GEORGIAN SMALL LETTER ZHAR) +test(0x1CA0, 0x10E0); // GEORGIAN MTAVRULI CAPITAL LETTER RAE, GEORGIAN LETTER RAE (GEORGIAN SMALL LETTER RAE) +test(0x1CA1, 0x10E1); // GEORGIAN MTAVRULI CAPITAL LETTER SAN, GEORGIAN LETTER SAN (GEORGIAN SMALL LETTER SAN) +test(0x1CA2, 0x10E2); // GEORGIAN MTAVRULI CAPITAL LETTER TAR, GEORGIAN LETTER TAR (GEORGIAN SMALL LETTER TAR) +test(0x1CA3, 0x10E3); // GEORGIAN MTAVRULI CAPITAL LETTER UN, GEORGIAN LETTER UN (GEORGIAN SMALL LETTER UN) +test(0x1CA4, 0x10E4); // GEORGIAN MTAVRULI CAPITAL LETTER PHAR, GEORGIAN LETTER PHAR (GEORGIAN SMALL LETTER PHAR) +test(0x1CA5, 0x10E5); // GEORGIAN MTAVRULI CAPITAL LETTER KHAR, GEORGIAN LETTER KHAR (GEORGIAN SMALL LETTER KHAR) +test(0x1CA6, 0x10E6); // GEORGIAN MTAVRULI CAPITAL LETTER GHAN, GEORGIAN LETTER GHAN (GEORGIAN SMALL LETTER GHAN) +test(0x1CA7, 0x10E7); // GEORGIAN MTAVRULI CAPITAL LETTER QAR, GEORGIAN LETTER QAR (GEORGIAN SMALL LETTER QAR) +test(0x1CA8, 0x10E8); // GEORGIAN MTAVRULI CAPITAL LETTER SHIN, GEORGIAN LETTER SHIN (GEORGIAN SMALL LETTER SHIN) +test(0x1CA9, 0x10E9); // GEORGIAN MTAVRULI CAPITAL LETTER CHIN, GEORGIAN LETTER CHIN (GEORGIAN SMALL LETTER CHIN) +test(0x1CAA, 0x10EA); // GEORGIAN MTAVRULI CAPITAL LETTER CAN, GEORGIAN LETTER CAN (GEORGIAN SMALL LETTER CAN) +test(0x1CAB, 0x10EB); // GEORGIAN MTAVRULI CAPITAL LETTER JIL, GEORGIAN LETTER JIL (GEORGIAN SMALL LETTER JIL) +test(0x1CAC, 0x10EC); // GEORGIAN MTAVRULI CAPITAL LETTER CIL, GEORGIAN LETTER CIL (GEORGIAN SMALL LETTER CIL) +test(0x1CAD, 0x10ED); // GEORGIAN MTAVRULI CAPITAL LETTER CHAR, GEORGIAN LETTER CHAR (GEORGIAN SMALL LETTER CHAR) +test(0x1CAE, 0x10EE); // GEORGIAN MTAVRULI CAPITAL LETTER XAN, GEORGIAN LETTER XAN (GEORGIAN SMALL LETTER XAN) +test(0x1CAF, 0x10EF); // GEORGIAN MTAVRULI CAPITAL LETTER JHAN, GEORGIAN LETTER JHAN (GEORGIAN SMALL LETTER JHAN) +test(0x1CB0, 0x10F0); // GEORGIAN MTAVRULI CAPITAL LETTER HAE, GEORGIAN LETTER HAE (GEORGIAN SMALL LETTER HAE) +test(0x1CB1, 0x10F1); // GEORGIAN MTAVRULI CAPITAL LETTER HE, GEORGIAN LETTER HE (GEORGIAN SMALL LETTER HE) +test(0x1CB2, 0x10F2); // GEORGIAN MTAVRULI CAPITAL LETTER HIE, GEORGIAN LETTER HIE (GEORGIAN SMALL LETTER HIE) +test(0x1CB3, 0x10F3); // GEORGIAN MTAVRULI CAPITAL LETTER WE, GEORGIAN LETTER WE (GEORGIAN SMALL LETTER WE) +test(0x1CB4, 0x10F4); // GEORGIAN MTAVRULI CAPITAL LETTER HAR, GEORGIAN LETTER HAR (GEORGIAN SMALL LETTER HAR) +test(0x1CB5, 0x10F5); // GEORGIAN MTAVRULI CAPITAL LETTER HOE, GEORGIAN LETTER HOE (GEORGIAN SMALL LETTER HOE) +test(0x1CB6, 0x10F6); // GEORGIAN MTAVRULI CAPITAL LETTER FI, GEORGIAN LETTER FI (GEORGIAN SMALL LETTER FI) +test(0x1CB7, 0x10F7); // GEORGIAN MTAVRULI CAPITAL LETTER YN, GEORGIAN LETTER YN +test(0x1CB8, 0x10F8); // GEORGIAN MTAVRULI CAPITAL LETTER ELIFI, GEORGIAN LETTER ELIFI +test(0x1CB9, 0x10F9); // GEORGIAN MTAVRULI CAPITAL LETTER TURNED GAN, GEORGIAN LETTER TURNED GAN +test(0x1CBA, 0x10FA); // GEORGIAN MTAVRULI CAPITAL LETTER AIN, GEORGIAN LETTER AIN +test(0x1CBD, 0x10FD); // GEORGIAN MTAVRULI CAPITAL LETTER AEN, GEORGIAN LETTER AEN +test(0x1CBE, 0x10FE); // GEORGIAN MTAVRULI CAPITAL LETTER HARD SIGN, GEORGIAN LETTER HARD SIGN +test(0x1CBF, 0x10FF); // GEORGIAN MTAVRULI CAPITAL LETTER LABIAL SIGN, GEORGIAN LETTER LABIAL SIGN +test(0x1D79, 0xA77D); // LATIN SMALL LETTER INSULAR G, LATIN CAPITAL LETTER INSULAR G +test(0x1D7D, 0x2C63); // LATIN SMALL LETTER P WITH STROKE, LATIN CAPITAL LETTER P WITH STROKE +test(0x1D8E, 0xA7C6); // LATIN SMALL LETTER Z WITH PALATAL HOOK, LATIN CAPITAL LETTER Z WITH PALATAL HOOK +test(0x1E00, 0x1E01); // LATIN CAPITAL LETTER A WITH RING BELOW, LATIN SMALL LETTER A WITH RING BELOW +test(0x1E01, 0x1E00); // LATIN SMALL LETTER A WITH RING BELOW, LATIN CAPITAL LETTER A WITH RING BELOW +test(0x1E02, 0x1E03); // LATIN CAPITAL LETTER B WITH DOT ABOVE, LATIN SMALL LETTER B WITH DOT ABOVE +test(0x1E03, 0x1E02); // LATIN SMALL LETTER B WITH DOT ABOVE, LATIN CAPITAL LETTER B WITH DOT ABOVE +test(0x1E04, 0x1E05); // LATIN CAPITAL LETTER B WITH DOT BELOW, LATIN SMALL LETTER B WITH DOT BELOW +test(0x1E05, 0x1E04); // LATIN SMALL LETTER B WITH DOT BELOW, LATIN CAPITAL LETTER B WITH DOT BELOW +test(0x1E06, 0x1E07); // LATIN CAPITAL LETTER B WITH LINE BELOW, LATIN SMALL LETTER B WITH LINE BELOW +test(0x1E07, 0x1E06); // LATIN SMALL LETTER B WITH LINE BELOW, LATIN CAPITAL LETTER B WITH LINE BELOW +test(0x1E08, 0x1E09); // LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE, LATIN SMALL LETTER C WITH CEDILLA AND ACUTE +test(0x1E09, 0x1E08); // LATIN SMALL LETTER C WITH CEDILLA AND ACUTE, LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE +test(0x1E0A, 0x1E0B); // LATIN CAPITAL LETTER D WITH DOT ABOVE, LATIN SMALL LETTER D WITH DOT ABOVE +test(0x1E0B, 0x1E0A); // LATIN SMALL LETTER D WITH DOT ABOVE, LATIN CAPITAL LETTER D WITH DOT ABOVE +test(0x1E0C, 0x1E0D); // LATIN CAPITAL LETTER D WITH DOT BELOW, LATIN SMALL LETTER D WITH DOT BELOW +test(0x1E0D, 0x1E0C); // LATIN SMALL LETTER D WITH DOT BELOW, LATIN CAPITAL LETTER D WITH DOT BELOW +test(0x1E0E, 0x1E0F); // LATIN CAPITAL LETTER D WITH LINE BELOW, LATIN SMALL LETTER D WITH LINE BELOW +test(0x1E0F, 0x1E0E); // LATIN SMALL LETTER D WITH LINE BELOW, LATIN CAPITAL LETTER D WITH LINE BELOW +test(0x1E10, 0x1E11); // LATIN CAPITAL LETTER D WITH CEDILLA, LATIN SMALL LETTER D WITH CEDILLA +test(0x1E11, 0x1E10); // LATIN SMALL LETTER D WITH CEDILLA, LATIN CAPITAL LETTER D WITH CEDILLA +test(0x1E12, 0x1E13); // LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW, LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW +test(0x1E13, 0x1E12); // LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW, LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW +test(0x1E14, 0x1E15); // LATIN CAPITAL LETTER E WITH MACRON AND GRAVE, LATIN SMALL LETTER E WITH MACRON AND GRAVE +test(0x1E15, 0x1E14); // LATIN SMALL LETTER E WITH MACRON AND GRAVE, LATIN CAPITAL LETTER E WITH MACRON AND GRAVE +test(0x1E16, 0x1E17); // LATIN CAPITAL LETTER E WITH MACRON AND ACUTE, LATIN SMALL LETTER E WITH MACRON AND ACUTE +test(0x1E17, 0x1E16); // LATIN SMALL LETTER E WITH MACRON AND ACUTE, LATIN CAPITAL LETTER E WITH MACRON AND ACUTE +test(0x1E18, 0x1E19); // LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW, LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW +test(0x1E19, 0x1E18); // LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW, LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW +test(0x1E1A, 0x1E1B); // LATIN CAPITAL LETTER E WITH TILDE BELOW, LATIN SMALL LETTER E WITH TILDE BELOW +test(0x1E1B, 0x1E1A); // LATIN SMALL LETTER E WITH TILDE BELOW, LATIN CAPITAL LETTER E WITH TILDE BELOW +test(0x1E1C, 0x1E1D); // LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE, LATIN SMALL LETTER E WITH CEDILLA AND BREVE +test(0x1E1D, 0x1E1C); // LATIN SMALL LETTER E WITH CEDILLA AND BREVE, LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE +test(0x1E1E, 0x1E1F); // LATIN CAPITAL LETTER F WITH DOT ABOVE, LATIN SMALL LETTER F WITH DOT ABOVE +test(0x1E1F, 0x1E1E); // LATIN SMALL LETTER F WITH DOT ABOVE, LATIN CAPITAL LETTER F WITH DOT ABOVE +test(0x1E20, 0x1E21); // LATIN CAPITAL LETTER G WITH MACRON, LATIN SMALL LETTER G WITH MACRON +test(0x1E21, 0x1E20); // LATIN SMALL LETTER G WITH MACRON, LATIN CAPITAL LETTER G WITH MACRON +test(0x1E22, 0x1E23); // LATIN CAPITAL LETTER H WITH DOT ABOVE, LATIN SMALL LETTER H WITH DOT ABOVE +test(0x1E23, 0x1E22); // LATIN SMALL LETTER H WITH DOT ABOVE, LATIN CAPITAL LETTER H WITH DOT ABOVE +test(0x1E24, 0x1E25); // LATIN CAPITAL LETTER H WITH DOT BELOW, LATIN SMALL LETTER H WITH DOT BELOW +test(0x1E25, 0x1E24); // LATIN SMALL LETTER H WITH DOT BELOW, LATIN CAPITAL LETTER H WITH DOT BELOW +test(0x1E26, 0x1E27); // LATIN CAPITAL LETTER H WITH DIAERESIS, LATIN SMALL LETTER H WITH DIAERESIS +test(0x1E27, 0x1E26); // LATIN SMALL LETTER H WITH DIAERESIS, LATIN CAPITAL LETTER H WITH DIAERESIS +test(0x1E28, 0x1E29); // LATIN CAPITAL LETTER H WITH CEDILLA, LATIN SMALL LETTER H WITH CEDILLA +test(0x1E29, 0x1E28); // LATIN SMALL LETTER H WITH CEDILLA, LATIN CAPITAL LETTER H WITH CEDILLA +test(0x1E2A, 0x1E2B); // LATIN CAPITAL LETTER H WITH BREVE BELOW, LATIN SMALL LETTER H WITH BREVE BELOW +test(0x1E2B, 0x1E2A); // LATIN SMALL LETTER H WITH BREVE BELOW, LATIN CAPITAL LETTER H WITH BREVE BELOW +test(0x1E2C, 0x1E2D); // LATIN CAPITAL LETTER I WITH TILDE BELOW, LATIN SMALL LETTER I WITH TILDE BELOW +test(0x1E2D, 0x1E2C); // LATIN SMALL LETTER I WITH TILDE BELOW, LATIN CAPITAL LETTER I WITH TILDE BELOW +test(0x1E2E, 0x1E2F); // LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE, LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE +test(0x1E2F, 0x1E2E); // LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE, LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE +test(0x1E30, 0x1E31); // LATIN CAPITAL LETTER K WITH ACUTE, LATIN SMALL LETTER K WITH ACUTE +test(0x1E31, 0x1E30); // LATIN SMALL LETTER K WITH ACUTE, LATIN CAPITAL LETTER K WITH ACUTE +test(0x1E32, 0x1E33); // LATIN CAPITAL LETTER K WITH DOT BELOW, LATIN SMALL LETTER K WITH DOT BELOW +test(0x1E33, 0x1E32); // LATIN SMALL LETTER K WITH DOT BELOW, LATIN CAPITAL LETTER K WITH DOT BELOW +test(0x1E34, 0x1E35); // LATIN CAPITAL LETTER K WITH LINE BELOW, LATIN SMALL LETTER K WITH LINE BELOW +test(0x1E35, 0x1E34); // LATIN SMALL LETTER K WITH LINE BELOW, LATIN CAPITAL LETTER K WITH LINE BELOW +test(0x1E36, 0x1E37); // LATIN CAPITAL LETTER L WITH DOT BELOW, LATIN SMALL LETTER L WITH DOT BELOW +test(0x1E37, 0x1E36); // LATIN SMALL LETTER L WITH DOT BELOW, LATIN CAPITAL LETTER L WITH DOT BELOW +test(0x1E38, 0x1E39); // LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON, LATIN SMALL LETTER L WITH DOT BELOW AND MACRON +test(0x1E39, 0x1E38); // LATIN SMALL LETTER L WITH DOT BELOW AND MACRON, LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON +test(0x1E3A, 0x1E3B); // LATIN CAPITAL LETTER L WITH LINE BELOW, LATIN SMALL LETTER L WITH LINE BELOW +test(0x1E3B, 0x1E3A); // LATIN SMALL LETTER L WITH LINE BELOW, LATIN CAPITAL LETTER L WITH LINE BELOW +test(0x1E3C, 0x1E3D); // LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW, LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW +test(0x1E3D, 0x1E3C); // LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW, LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW +test(0x1E3E, 0x1E3F); // LATIN CAPITAL LETTER M WITH ACUTE, LATIN SMALL LETTER M WITH ACUTE +test(0x1E3F, 0x1E3E); // LATIN SMALL LETTER M WITH ACUTE, LATIN CAPITAL LETTER M WITH ACUTE +test(0x1E40, 0x1E41); // LATIN CAPITAL LETTER M WITH DOT ABOVE, LATIN SMALL LETTER M WITH DOT ABOVE +test(0x1E41, 0x1E40); // LATIN SMALL LETTER M WITH DOT ABOVE, LATIN CAPITAL LETTER M WITH DOT ABOVE +test(0x1E42, 0x1E43); // LATIN CAPITAL LETTER M WITH DOT BELOW, LATIN SMALL LETTER M WITH DOT BELOW +test(0x1E43, 0x1E42); // LATIN SMALL LETTER M WITH DOT BELOW, LATIN CAPITAL LETTER M WITH DOT BELOW +test(0x1E44, 0x1E45); // LATIN CAPITAL LETTER N WITH DOT ABOVE, LATIN SMALL LETTER N WITH DOT ABOVE +test(0x1E45, 0x1E44); // LATIN SMALL LETTER N WITH DOT ABOVE, LATIN CAPITAL LETTER N WITH DOT ABOVE +test(0x1E46, 0x1E47); // LATIN CAPITAL LETTER N WITH DOT BELOW, LATIN SMALL LETTER N WITH DOT BELOW +test(0x1E47, 0x1E46); // LATIN SMALL LETTER N WITH DOT BELOW, LATIN CAPITAL LETTER N WITH DOT BELOW +test(0x1E48, 0x1E49); // LATIN CAPITAL LETTER N WITH LINE BELOW, LATIN SMALL LETTER N WITH LINE BELOW +test(0x1E49, 0x1E48); // LATIN SMALL LETTER N WITH LINE BELOW, LATIN CAPITAL LETTER N WITH LINE BELOW +test(0x1E4A, 0x1E4B); // LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW, LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW +test(0x1E4B, 0x1E4A); // LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW, LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW +test(0x1E4C, 0x1E4D); // LATIN CAPITAL LETTER O WITH TILDE AND ACUTE, LATIN SMALL LETTER O WITH TILDE AND ACUTE +test(0x1E4D, 0x1E4C); // LATIN SMALL LETTER O WITH TILDE AND ACUTE, LATIN CAPITAL LETTER O WITH TILDE AND ACUTE +test(0x1E4E, 0x1E4F); // LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS, LATIN SMALL LETTER O WITH TILDE AND DIAERESIS +test(0x1E4F, 0x1E4E); // LATIN SMALL LETTER O WITH TILDE AND DIAERESIS, LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS +test(0x1E50, 0x1E51); // LATIN CAPITAL LETTER O WITH MACRON AND GRAVE, LATIN SMALL LETTER O WITH MACRON AND GRAVE +test(0x1E51, 0x1E50); // LATIN SMALL LETTER O WITH MACRON AND GRAVE, LATIN CAPITAL LETTER O WITH MACRON AND GRAVE +test(0x1E52, 0x1E53); // LATIN CAPITAL LETTER O WITH MACRON AND ACUTE, LATIN SMALL LETTER O WITH MACRON AND ACUTE +test(0x1E53, 0x1E52); // LATIN SMALL LETTER O WITH MACRON AND ACUTE, LATIN CAPITAL LETTER O WITH MACRON AND ACUTE +test(0x1E54, 0x1E55); // LATIN CAPITAL LETTER P WITH ACUTE, LATIN SMALL LETTER P WITH ACUTE +test(0x1E55, 0x1E54); // LATIN SMALL LETTER P WITH ACUTE, LATIN CAPITAL LETTER P WITH ACUTE +test(0x1E56, 0x1E57); // LATIN CAPITAL LETTER P WITH DOT ABOVE, LATIN SMALL LETTER P WITH DOT ABOVE +test(0x1E57, 0x1E56); // LATIN SMALL LETTER P WITH DOT ABOVE, LATIN CAPITAL LETTER P WITH DOT ABOVE +test(0x1E58, 0x1E59); // LATIN CAPITAL LETTER R WITH DOT ABOVE, LATIN SMALL LETTER R WITH DOT ABOVE +test(0x1E59, 0x1E58); // LATIN SMALL LETTER R WITH DOT ABOVE, LATIN CAPITAL LETTER R WITH DOT ABOVE +test(0x1E5A, 0x1E5B); // LATIN CAPITAL LETTER R WITH DOT BELOW, LATIN SMALL LETTER R WITH DOT BELOW +test(0x1E5B, 0x1E5A); // LATIN SMALL LETTER R WITH DOT BELOW, LATIN CAPITAL LETTER R WITH DOT BELOW +test(0x1E5C, 0x1E5D); // LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON, LATIN SMALL LETTER R WITH DOT BELOW AND MACRON +test(0x1E5D, 0x1E5C); // LATIN SMALL LETTER R WITH DOT BELOW AND MACRON, LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON +test(0x1E5E, 0x1E5F); // LATIN CAPITAL LETTER R WITH LINE BELOW, LATIN SMALL LETTER R WITH LINE BELOW +test(0x1E5F, 0x1E5E); // LATIN SMALL LETTER R WITH LINE BELOW, LATIN CAPITAL LETTER R WITH LINE BELOW +test(0x1E60, 0x1E61, 0x1E9B); // LATIN CAPITAL LETTER S WITH DOT ABOVE, LATIN SMALL LETTER S WITH DOT ABOVE, LATIN SMALL LETTER LONG S WITH DOT ABOVE +test(0x1E61, 0x1E60, 0x1E9B); // LATIN SMALL LETTER S WITH DOT ABOVE, LATIN CAPITAL LETTER S WITH DOT ABOVE, LATIN SMALL LETTER LONG S WITH DOT ABOVE +test(0x1E62, 0x1E63); // LATIN CAPITAL LETTER S WITH DOT BELOW, LATIN SMALL LETTER S WITH DOT BELOW +test(0x1E63, 0x1E62); // LATIN SMALL LETTER S WITH DOT BELOW, LATIN CAPITAL LETTER S WITH DOT BELOW +test(0x1E64, 0x1E65); // LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE, LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE +test(0x1E65, 0x1E64); // LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE, LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE +test(0x1E66, 0x1E67); // LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE, LATIN SMALL LETTER S WITH CARON AND DOT ABOVE +test(0x1E67, 0x1E66); // LATIN SMALL LETTER S WITH CARON AND DOT ABOVE, LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE +test(0x1E68, 0x1E69); // LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE, LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE +test(0x1E69, 0x1E68); // LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE, LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE +test(0x1E6A, 0x1E6B); // LATIN CAPITAL LETTER T WITH DOT ABOVE, LATIN SMALL LETTER T WITH DOT ABOVE +test(0x1E6B, 0x1E6A); // LATIN SMALL LETTER T WITH DOT ABOVE, LATIN CAPITAL LETTER T WITH DOT ABOVE +test(0x1E6C, 0x1E6D); // LATIN CAPITAL LETTER T WITH DOT BELOW, LATIN SMALL LETTER T WITH DOT BELOW +test(0x1E6D, 0x1E6C); // LATIN SMALL LETTER T WITH DOT BELOW, LATIN CAPITAL LETTER T WITH DOT BELOW +test(0x1E6E, 0x1E6F); // LATIN CAPITAL LETTER T WITH LINE BELOW, LATIN SMALL LETTER T WITH LINE BELOW +test(0x1E6F, 0x1E6E); // LATIN SMALL LETTER T WITH LINE BELOW, LATIN CAPITAL LETTER T WITH LINE BELOW +test(0x1E70, 0x1E71); // LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW, LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW +test(0x1E71, 0x1E70); // LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW, LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW +test(0x1E72, 0x1E73); // LATIN CAPITAL LETTER U WITH DIAERESIS BELOW, LATIN SMALL LETTER U WITH DIAERESIS BELOW +test(0x1E73, 0x1E72); // LATIN SMALL LETTER U WITH DIAERESIS BELOW, LATIN CAPITAL LETTER U WITH DIAERESIS BELOW +test(0x1E74, 0x1E75); // LATIN CAPITAL LETTER U WITH TILDE BELOW, LATIN SMALL LETTER U WITH TILDE BELOW +test(0x1E75, 0x1E74); // LATIN SMALL LETTER U WITH TILDE BELOW, LATIN CAPITAL LETTER U WITH TILDE BELOW +test(0x1E76, 0x1E77); // LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW, LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW +test(0x1E77, 0x1E76); // LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW, LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW +test(0x1E78, 0x1E79); // LATIN CAPITAL LETTER U WITH TILDE AND ACUTE, LATIN SMALL LETTER U WITH TILDE AND ACUTE +test(0x1E79, 0x1E78); // LATIN SMALL LETTER U WITH TILDE AND ACUTE, LATIN CAPITAL LETTER U WITH TILDE AND ACUTE +test(0x1E7A, 0x1E7B); // LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS, LATIN SMALL LETTER U WITH MACRON AND DIAERESIS +test(0x1E7B, 0x1E7A); // LATIN SMALL LETTER U WITH MACRON AND DIAERESIS, LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS +test(0x1E7C, 0x1E7D); // LATIN CAPITAL LETTER V WITH TILDE, LATIN SMALL LETTER V WITH TILDE +test(0x1E7D, 0x1E7C); // LATIN SMALL LETTER V WITH TILDE, LATIN CAPITAL LETTER V WITH TILDE +test(0x1E7E, 0x1E7F); // LATIN CAPITAL LETTER V WITH DOT BELOW, LATIN SMALL LETTER V WITH DOT BELOW +test(0x1E7F, 0x1E7E); // LATIN SMALL LETTER V WITH DOT BELOW, LATIN CAPITAL LETTER V WITH DOT BELOW +test(0x1E80, 0x1E81); // LATIN CAPITAL LETTER W WITH GRAVE, LATIN SMALL LETTER W WITH GRAVE +test(0x1E81, 0x1E80); // LATIN SMALL LETTER W WITH GRAVE, LATIN CAPITAL LETTER W WITH GRAVE +test(0x1E82, 0x1E83); // LATIN CAPITAL LETTER W WITH ACUTE, LATIN SMALL LETTER W WITH ACUTE +test(0x1E83, 0x1E82); // LATIN SMALL LETTER W WITH ACUTE, LATIN CAPITAL LETTER W WITH ACUTE +test(0x1E84, 0x1E85); // LATIN CAPITAL LETTER W WITH DIAERESIS, LATIN SMALL LETTER W WITH DIAERESIS +test(0x1E85, 0x1E84); // LATIN SMALL LETTER W WITH DIAERESIS, LATIN CAPITAL LETTER W WITH DIAERESIS +test(0x1E86, 0x1E87); // LATIN CAPITAL LETTER W WITH DOT ABOVE, LATIN SMALL LETTER W WITH DOT ABOVE +test(0x1E87, 0x1E86); // LATIN SMALL LETTER W WITH DOT ABOVE, LATIN CAPITAL LETTER W WITH DOT ABOVE +test(0x1E88, 0x1E89); // LATIN CAPITAL LETTER W WITH DOT BELOW, LATIN SMALL LETTER W WITH DOT BELOW +test(0x1E89, 0x1E88); // LATIN SMALL LETTER W WITH DOT BELOW, LATIN CAPITAL LETTER W WITH DOT BELOW +test(0x1E8A, 0x1E8B); // LATIN CAPITAL LETTER X WITH DOT ABOVE, LATIN SMALL LETTER X WITH DOT ABOVE +test(0x1E8B, 0x1E8A); // LATIN SMALL LETTER X WITH DOT ABOVE, LATIN CAPITAL LETTER X WITH DOT ABOVE +test(0x1E8C, 0x1E8D); // LATIN CAPITAL LETTER X WITH DIAERESIS, LATIN SMALL LETTER X WITH DIAERESIS +test(0x1E8D, 0x1E8C); // LATIN SMALL LETTER X WITH DIAERESIS, LATIN CAPITAL LETTER X WITH DIAERESIS +test(0x1E8E, 0x1E8F); // LATIN CAPITAL LETTER Y WITH DOT ABOVE, LATIN SMALL LETTER Y WITH DOT ABOVE +test(0x1E8F, 0x1E8E); // LATIN SMALL LETTER Y WITH DOT ABOVE, LATIN CAPITAL LETTER Y WITH DOT ABOVE +test(0x1E90, 0x1E91); // LATIN CAPITAL LETTER Z WITH CIRCUMFLEX, LATIN SMALL LETTER Z WITH CIRCUMFLEX +test(0x1E91, 0x1E90); // LATIN SMALL LETTER Z WITH CIRCUMFLEX, LATIN CAPITAL LETTER Z WITH CIRCUMFLEX +test(0x1E92, 0x1E93); // LATIN CAPITAL LETTER Z WITH DOT BELOW, LATIN SMALL LETTER Z WITH DOT BELOW +test(0x1E93, 0x1E92); // LATIN SMALL LETTER Z WITH DOT BELOW, LATIN CAPITAL LETTER Z WITH DOT BELOW +test(0x1E94, 0x1E95); // LATIN CAPITAL LETTER Z WITH LINE BELOW, LATIN SMALL LETTER Z WITH LINE BELOW +test(0x1E95, 0x1E94); // LATIN SMALL LETTER Z WITH LINE BELOW, LATIN CAPITAL LETTER Z WITH LINE BELOW +test(0x1E9B, 0x1E61, 0x1E60); // LATIN SMALL LETTER LONG S WITH DOT ABOVE, LATIN SMALL LETTER S WITH DOT ABOVE, LATIN CAPITAL LETTER S WITH DOT ABOVE +test(0x1E9E, 0x00DF); // LATIN CAPITAL LETTER SHARP S, LATIN SMALL LETTER SHARP S +test(0x1EA0, 0x1EA1); // LATIN CAPITAL LETTER A WITH DOT BELOW, LATIN SMALL LETTER A WITH DOT BELOW +test(0x1EA1, 0x1EA0); // LATIN SMALL LETTER A WITH DOT BELOW, LATIN CAPITAL LETTER A WITH DOT BELOW +test(0x1EA2, 0x1EA3); // LATIN CAPITAL LETTER A WITH HOOK ABOVE, LATIN SMALL LETTER A WITH HOOK ABOVE +test(0x1EA3, 0x1EA2); // LATIN SMALL LETTER A WITH HOOK ABOVE, LATIN CAPITAL LETTER A WITH HOOK ABOVE +test(0x1EA4, 0x1EA5); // LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE, LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE +test(0x1EA5, 0x1EA4); // LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE, LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE +test(0x1EA6, 0x1EA7); // LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE, LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE +test(0x1EA7, 0x1EA6); // LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE, LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE +test(0x1EA8, 0x1EA9); // LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE, LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE +test(0x1EA9, 0x1EA8); // LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE, LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE +test(0x1EAA, 0x1EAB); // LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE, LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE +test(0x1EAB, 0x1EAA); // LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE, LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE +test(0x1EAC, 0x1EAD); // LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW, LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW +test(0x1EAD, 0x1EAC); // LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW, LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW +test(0x1EAE, 0x1EAF); // LATIN CAPITAL LETTER A WITH BREVE AND ACUTE, LATIN SMALL LETTER A WITH BREVE AND ACUTE +test(0x1EAF, 0x1EAE); // LATIN SMALL LETTER A WITH BREVE AND ACUTE, LATIN CAPITAL LETTER A WITH BREVE AND ACUTE +test(0x1EB0, 0x1EB1); // LATIN CAPITAL LETTER A WITH BREVE AND GRAVE, LATIN SMALL LETTER A WITH BREVE AND GRAVE +test(0x1EB1, 0x1EB0); // LATIN SMALL LETTER A WITH BREVE AND GRAVE, LATIN CAPITAL LETTER A WITH BREVE AND GRAVE +test(0x1EB2, 0x1EB3); // LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE, LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE +test(0x1EB3, 0x1EB2); // LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE, LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE +test(0x1EB4, 0x1EB5); // LATIN CAPITAL LETTER A WITH BREVE AND TILDE, LATIN SMALL LETTER A WITH BREVE AND TILDE +test(0x1EB5, 0x1EB4); // LATIN SMALL LETTER A WITH BREVE AND TILDE, LATIN CAPITAL LETTER A WITH BREVE AND TILDE +test(0x1EB6, 0x1EB7); // LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW, LATIN SMALL LETTER A WITH BREVE AND DOT BELOW +test(0x1EB7, 0x1EB6); // LATIN SMALL LETTER A WITH BREVE AND DOT BELOW, LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW +test(0x1EB8, 0x1EB9); // LATIN CAPITAL LETTER E WITH DOT BELOW, LATIN SMALL LETTER E WITH DOT BELOW +test(0x1EB9, 0x1EB8); // LATIN SMALL LETTER E WITH DOT BELOW, LATIN CAPITAL LETTER E WITH DOT BELOW +test(0x1EBA, 0x1EBB); // LATIN CAPITAL LETTER E WITH HOOK ABOVE, LATIN SMALL LETTER E WITH HOOK ABOVE +test(0x1EBB, 0x1EBA); // LATIN SMALL LETTER E WITH HOOK ABOVE, LATIN CAPITAL LETTER E WITH HOOK ABOVE +test(0x1EBC, 0x1EBD); // LATIN CAPITAL LETTER E WITH TILDE, LATIN SMALL LETTER E WITH TILDE +test(0x1EBD, 0x1EBC); // LATIN SMALL LETTER E WITH TILDE, LATIN CAPITAL LETTER E WITH TILDE +test(0x1EBE, 0x1EBF); // LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE, LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE +test(0x1EBF, 0x1EBE); // LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE, LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE +test(0x1EC0, 0x1EC1); // LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE, LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE +test(0x1EC1, 0x1EC0); // LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE, LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE +test(0x1EC2, 0x1EC3); // LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE, LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE +test(0x1EC3, 0x1EC2); // LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE, LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE +test(0x1EC4, 0x1EC5); // LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE, LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE +test(0x1EC5, 0x1EC4); // LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE, LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE +test(0x1EC6, 0x1EC7); // LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW, LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW +test(0x1EC7, 0x1EC6); // LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW, LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW +test(0x1EC8, 0x1EC9); // LATIN CAPITAL LETTER I WITH HOOK ABOVE, LATIN SMALL LETTER I WITH HOOK ABOVE +test(0x1EC9, 0x1EC8); // LATIN SMALL LETTER I WITH HOOK ABOVE, LATIN CAPITAL LETTER I WITH HOOK ABOVE +test(0x1ECA, 0x1ECB); // LATIN CAPITAL LETTER I WITH DOT BELOW, LATIN SMALL LETTER I WITH DOT BELOW +test(0x1ECB, 0x1ECA); // LATIN SMALL LETTER I WITH DOT BELOW, LATIN CAPITAL LETTER I WITH DOT BELOW +test(0x1ECC, 0x1ECD); // LATIN CAPITAL LETTER O WITH DOT BELOW, LATIN SMALL LETTER O WITH DOT BELOW +test(0x1ECD, 0x1ECC); // LATIN SMALL LETTER O WITH DOT BELOW, LATIN CAPITAL LETTER O WITH DOT BELOW +test(0x1ECE, 0x1ECF); // LATIN CAPITAL LETTER O WITH HOOK ABOVE, LATIN SMALL LETTER O WITH HOOK ABOVE +test(0x1ECF, 0x1ECE); // LATIN SMALL LETTER O WITH HOOK ABOVE, LATIN CAPITAL LETTER O WITH HOOK ABOVE +test(0x1ED0, 0x1ED1); // LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE, LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE +test(0x1ED1, 0x1ED0); // LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE, LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE +test(0x1ED2, 0x1ED3); // LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE, LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE +test(0x1ED3, 0x1ED2); // LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE, LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE +test(0x1ED4, 0x1ED5); // LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE, LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE +test(0x1ED5, 0x1ED4); // LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE, LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE +test(0x1ED6, 0x1ED7); // LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE, LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE +test(0x1ED7, 0x1ED6); // LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE, LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE +test(0x1ED8, 0x1ED9); // LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW, LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW +test(0x1ED9, 0x1ED8); // LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW, LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW +test(0x1EDA, 0x1EDB); // LATIN CAPITAL LETTER O WITH HORN AND ACUTE, LATIN SMALL LETTER O WITH HORN AND ACUTE +test(0x1EDB, 0x1EDA); // LATIN SMALL LETTER O WITH HORN AND ACUTE, LATIN CAPITAL LETTER O WITH HORN AND ACUTE +test(0x1EDC, 0x1EDD); // LATIN CAPITAL LETTER O WITH HORN AND GRAVE, LATIN SMALL LETTER O WITH HORN AND GRAVE +test(0x1EDD, 0x1EDC); // LATIN SMALL LETTER O WITH HORN AND GRAVE, LATIN CAPITAL LETTER O WITH HORN AND GRAVE +test(0x1EDE, 0x1EDF); // LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE, LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE +test(0x1EDF, 0x1EDE); // LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE, LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE +test(0x1EE0, 0x1EE1); // LATIN CAPITAL LETTER O WITH HORN AND TILDE, LATIN SMALL LETTER O WITH HORN AND TILDE +test(0x1EE1, 0x1EE0); // LATIN SMALL LETTER O WITH HORN AND TILDE, LATIN CAPITAL LETTER O WITH HORN AND TILDE +test(0x1EE2, 0x1EE3); // LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW, LATIN SMALL LETTER O WITH HORN AND DOT BELOW +test(0x1EE3, 0x1EE2); // LATIN SMALL LETTER O WITH HORN AND DOT BELOW, LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW +test(0x1EE4, 0x1EE5); // LATIN CAPITAL LETTER U WITH DOT BELOW, LATIN SMALL LETTER U WITH DOT BELOW +test(0x1EE5, 0x1EE4); // LATIN SMALL LETTER U WITH DOT BELOW, LATIN CAPITAL LETTER U WITH DOT BELOW +test(0x1EE6, 0x1EE7); // LATIN CAPITAL LETTER U WITH HOOK ABOVE, LATIN SMALL LETTER U WITH HOOK ABOVE +test(0x1EE7, 0x1EE6); // LATIN SMALL LETTER U WITH HOOK ABOVE, LATIN CAPITAL LETTER U WITH HOOK ABOVE +test(0x1EE8, 0x1EE9); // LATIN CAPITAL LETTER U WITH HORN AND ACUTE, LATIN SMALL LETTER U WITH HORN AND ACUTE +test(0x1EE9, 0x1EE8); // LATIN SMALL LETTER U WITH HORN AND ACUTE, LATIN CAPITAL LETTER U WITH HORN AND ACUTE +test(0x1EEA, 0x1EEB); // LATIN CAPITAL LETTER U WITH HORN AND GRAVE, LATIN SMALL LETTER U WITH HORN AND GRAVE +test(0x1EEB, 0x1EEA); // LATIN SMALL LETTER U WITH HORN AND GRAVE, LATIN CAPITAL LETTER U WITH HORN AND GRAVE +test(0x1EEC, 0x1EED); // LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE, LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE +test(0x1EED, 0x1EEC); // LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE, LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE +test(0x1EEE, 0x1EEF); // LATIN CAPITAL LETTER U WITH HORN AND TILDE, LATIN SMALL LETTER U WITH HORN AND TILDE +test(0x1EEF, 0x1EEE); // LATIN SMALL LETTER U WITH HORN AND TILDE, LATIN CAPITAL LETTER U WITH HORN AND TILDE +test(0x1EF0, 0x1EF1); // LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW, LATIN SMALL LETTER U WITH HORN AND DOT BELOW +test(0x1EF1, 0x1EF0); // LATIN SMALL LETTER U WITH HORN AND DOT BELOW, LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW +test(0x1EF2, 0x1EF3); // LATIN CAPITAL LETTER Y WITH GRAVE, LATIN SMALL LETTER Y WITH GRAVE +test(0x1EF3, 0x1EF2); // LATIN SMALL LETTER Y WITH GRAVE, LATIN CAPITAL LETTER Y WITH GRAVE +test(0x1EF4, 0x1EF5); // LATIN CAPITAL LETTER Y WITH DOT BELOW, LATIN SMALL LETTER Y WITH DOT BELOW +test(0x1EF5, 0x1EF4); // LATIN SMALL LETTER Y WITH DOT BELOW, LATIN CAPITAL LETTER Y WITH DOT BELOW +test(0x1EF6, 0x1EF7); // LATIN CAPITAL LETTER Y WITH HOOK ABOVE, LATIN SMALL LETTER Y WITH HOOK ABOVE +test(0x1EF7, 0x1EF6); // LATIN SMALL LETTER Y WITH HOOK ABOVE, LATIN CAPITAL LETTER Y WITH HOOK ABOVE +test(0x1EF8, 0x1EF9); // LATIN CAPITAL LETTER Y WITH TILDE, LATIN SMALL LETTER Y WITH TILDE +test(0x1EF9, 0x1EF8); // LATIN SMALL LETTER Y WITH TILDE, LATIN CAPITAL LETTER Y WITH TILDE +test(0x1EFA, 0x1EFB); // LATIN CAPITAL LETTER MIDDLE-WELSH LL, LATIN SMALL LETTER MIDDLE-WELSH LL +test(0x1EFB, 0x1EFA); // LATIN SMALL LETTER MIDDLE-WELSH LL, LATIN CAPITAL LETTER MIDDLE-WELSH LL +test(0x1EFC, 0x1EFD); // LATIN CAPITAL LETTER MIDDLE-WELSH V, LATIN SMALL LETTER MIDDLE-WELSH V +test(0x1EFD, 0x1EFC); // LATIN SMALL LETTER MIDDLE-WELSH V, LATIN CAPITAL LETTER MIDDLE-WELSH V +test(0x1EFE, 0x1EFF); // LATIN CAPITAL LETTER Y WITH LOOP, LATIN SMALL LETTER Y WITH LOOP +test(0x1EFF, 0x1EFE); // LATIN SMALL LETTER Y WITH LOOP, LATIN CAPITAL LETTER Y WITH LOOP +test(0x1F00, 0x1F08); // GREEK SMALL LETTER ALPHA WITH PSILI, GREEK CAPITAL LETTER ALPHA WITH PSILI +test(0x1F01, 0x1F09); // GREEK SMALL LETTER ALPHA WITH DASIA, GREEK CAPITAL LETTER ALPHA WITH DASIA +test(0x1F02, 0x1F0A); // GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA, GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA +test(0x1F03, 0x1F0B); // GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA, GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA +test(0x1F04, 0x1F0C); // GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA, GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA +test(0x1F05, 0x1F0D); // GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA, GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA +test(0x1F06, 0x1F0E); // GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI, GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI +test(0x1F07, 0x1F0F); // GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI, GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI +test(0x1F08, 0x1F00); // GREEK CAPITAL LETTER ALPHA WITH PSILI, GREEK SMALL LETTER ALPHA WITH PSILI +test(0x1F09, 0x1F01); // GREEK CAPITAL LETTER ALPHA WITH DASIA, GREEK SMALL LETTER ALPHA WITH DASIA +test(0x1F0A, 0x1F02); // GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA, GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA +test(0x1F0B, 0x1F03); // GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA, GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA +test(0x1F0C, 0x1F04); // GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA, GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA +test(0x1F0D, 0x1F05); // GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA, GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA +test(0x1F0E, 0x1F06); // GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI, GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI +test(0x1F0F, 0x1F07); // GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI, GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI +test(0x1F10, 0x1F18); // GREEK SMALL LETTER EPSILON WITH PSILI, GREEK CAPITAL LETTER EPSILON WITH PSILI +test(0x1F11, 0x1F19); // GREEK SMALL LETTER EPSILON WITH DASIA, GREEK CAPITAL LETTER EPSILON WITH DASIA +test(0x1F12, 0x1F1A); // GREEK SMALL LETTER EPSILON WITH PSILI AND VARIA, GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA +test(0x1F13, 0x1F1B); // GREEK SMALL LETTER EPSILON WITH DASIA AND VARIA, GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA +test(0x1F14, 0x1F1C); // GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA, GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA +test(0x1F15, 0x1F1D); // GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA, GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA +test(0x1F18, 0x1F10); // GREEK CAPITAL LETTER EPSILON WITH PSILI, GREEK SMALL LETTER EPSILON WITH PSILI +test(0x1F19, 0x1F11); // GREEK CAPITAL LETTER EPSILON WITH DASIA, GREEK SMALL LETTER EPSILON WITH DASIA +test(0x1F1A, 0x1F12); // GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA, GREEK SMALL LETTER EPSILON WITH PSILI AND VARIA +test(0x1F1B, 0x1F13); // GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA, GREEK SMALL LETTER EPSILON WITH DASIA AND VARIA +test(0x1F1C, 0x1F14); // GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA, GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA +test(0x1F1D, 0x1F15); // GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA, GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA +test(0x1F20, 0x1F28); // GREEK SMALL LETTER ETA WITH PSILI, GREEK CAPITAL LETTER ETA WITH PSILI +test(0x1F21, 0x1F29); // GREEK SMALL LETTER ETA WITH DASIA, GREEK CAPITAL LETTER ETA WITH DASIA +test(0x1F22, 0x1F2A); // GREEK SMALL LETTER ETA WITH PSILI AND VARIA, GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA +test(0x1F23, 0x1F2B); // GREEK SMALL LETTER ETA WITH DASIA AND VARIA, GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA +test(0x1F24, 0x1F2C); // GREEK SMALL LETTER ETA WITH PSILI AND OXIA, GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA +test(0x1F25, 0x1F2D); // GREEK SMALL LETTER ETA WITH DASIA AND OXIA, GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA +test(0x1F26, 0x1F2E); // GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI, GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI +test(0x1F27, 0x1F2F); // GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI, GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI +test(0x1F28, 0x1F20); // GREEK CAPITAL LETTER ETA WITH PSILI, GREEK SMALL LETTER ETA WITH PSILI +test(0x1F29, 0x1F21); // GREEK CAPITAL LETTER ETA WITH DASIA, GREEK SMALL LETTER ETA WITH DASIA +test(0x1F2A, 0x1F22); // GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA, GREEK SMALL LETTER ETA WITH PSILI AND VARIA +test(0x1F2B, 0x1F23); // GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA, GREEK SMALL LETTER ETA WITH DASIA AND VARIA +test(0x1F2C, 0x1F24); // GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA, GREEK SMALL LETTER ETA WITH PSILI AND OXIA +test(0x1F2D, 0x1F25); // GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA, GREEK SMALL LETTER ETA WITH DASIA AND OXIA +test(0x1F2E, 0x1F26); // GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI, GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI +test(0x1F2F, 0x1F27); // GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI, GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI +test(0x1F30, 0x1F38); // GREEK SMALL LETTER IOTA WITH PSILI, GREEK CAPITAL LETTER IOTA WITH PSILI +test(0x1F31, 0x1F39); // GREEK SMALL LETTER IOTA WITH DASIA, GREEK CAPITAL LETTER IOTA WITH DASIA +test(0x1F32, 0x1F3A); // GREEK SMALL LETTER IOTA WITH PSILI AND VARIA, GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA +test(0x1F33, 0x1F3B); // GREEK SMALL LETTER IOTA WITH DASIA AND VARIA, GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA +test(0x1F34, 0x1F3C); // GREEK SMALL LETTER IOTA WITH PSILI AND OXIA, GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA +test(0x1F35, 0x1F3D); // GREEK SMALL LETTER IOTA WITH DASIA AND OXIA, GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA +test(0x1F36, 0x1F3E); // GREEK SMALL LETTER IOTA WITH PSILI AND PERISPOMENI, GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI +test(0x1F37, 0x1F3F); // GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI, GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI +test(0x1F38, 0x1F30); // GREEK CAPITAL LETTER IOTA WITH PSILI, GREEK SMALL LETTER IOTA WITH PSILI +test(0x1F39, 0x1F31); // GREEK CAPITAL LETTER IOTA WITH DASIA, GREEK SMALL LETTER IOTA WITH DASIA +test(0x1F3A, 0x1F32); // GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA, GREEK SMALL LETTER IOTA WITH PSILI AND VARIA +test(0x1F3B, 0x1F33); // GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA, GREEK SMALL LETTER IOTA WITH DASIA AND VARIA +test(0x1F3C, 0x1F34); // GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA, GREEK SMALL LETTER IOTA WITH PSILI AND OXIA +test(0x1F3D, 0x1F35); // GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA, GREEK SMALL LETTER IOTA WITH DASIA AND OXIA +test(0x1F3E, 0x1F36); // GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI, GREEK SMALL LETTER IOTA WITH PSILI AND PERISPOMENI +test(0x1F3F, 0x1F37); // GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI, GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI +test(0x1F40, 0x1F48); // GREEK SMALL LETTER OMICRON WITH PSILI, GREEK CAPITAL LETTER OMICRON WITH PSILI +test(0x1F41, 0x1F49); // GREEK SMALL LETTER OMICRON WITH DASIA, GREEK CAPITAL LETTER OMICRON WITH DASIA +test(0x1F42, 0x1F4A); // GREEK SMALL LETTER OMICRON WITH PSILI AND VARIA, GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA +test(0x1F43, 0x1F4B); // GREEK SMALL LETTER OMICRON WITH DASIA AND VARIA, GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA +test(0x1F44, 0x1F4C); // GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA, GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA +test(0x1F45, 0x1F4D); // GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA, GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA +test(0x1F48, 0x1F40); // GREEK CAPITAL LETTER OMICRON WITH PSILI, GREEK SMALL LETTER OMICRON WITH PSILI +test(0x1F49, 0x1F41); // GREEK CAPITAL LETTER OMICRON WITH DASIA, GREEK SMALL LETTER OMICRON WITH DASIA +test(0x1F4A, 0x1F42); // GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA, GREEK SMALL LETTER OMICRON WITH PSILI AND VARIA +test(0x1F4B, 0x1F43); // GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA, GREEK SMALL LETTER OMICRON WITH DASIA AND VARIA +test(0x1F4C, 0x1F44); // GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA, GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA +test(0x1F4D, 0x1F45); // GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA, GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA +test(0x1F51, 0x1F59); // GREEK SMALL LETTER UPSILON WITH DASIA, GREEK CAPITAL LETTER UPSILON WITH DASIA +test(0x1F53, 0x1F5B); // GREEK SMALL LETTER UPSILON WITH DASIA AND VARIA, GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA +test(0x1F55, 0x1F5D); // GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA, GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA +test(0x1F57, 0x1F5F); // GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI, GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI +test(0x1F59, 0x1F51); // GREEK CAPITAL LETTER UPSILON WITH DASIA, GREEK SMALL LETTER UPSILON WITH DASIA +test(0x1F5B, 0x1F53); // GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA, GREEK SMALL LETTER UPSILON WITH DASIA AND VARIA +test(0x1F5D, 0x1F55); // GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA, GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA +test(0x1F5F, 0x1F57); // GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI, GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI +test(0x1F60, 0x1F68); // GREEK SMALL LETTER OMEGA WITH PSILI, GREEK CAPITAL LETTER OMEGA WITH PSILI +test(0x1F61, 0x1F69); // GREEK SMALL LETTER OMEGA WITH DASIA, GREEK CAPITAL LETTER OMEGA WITH DASIA +test(0x1F62, 0x1F6A); // GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA, GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA +test(0x1F63, 0x1F6B); // GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA, GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA +test(0x1F64, 0x1F6C); // GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA, GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA +test(0x1F65, 0x1F6D); // GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA, GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA +test(0x1F66, 0x1F6E); // GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI, GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI +test(0x1F67, 0x1F6F); // GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI, GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI +test(0x1F68, 0x1F60); // GREEK CAPITAL LETTER OMEGA WITH PSILI, GREEK SMALL LETTER OMEGA WITH PSILI +test(0x1F69, 0x1F61); // GREEK CAPITAL LETTER OMEGA WITH DASIA, GREEK SMALL LETTER OMEGA WITH DASIA +test(0x1F6A, 0x1F62); // GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA, GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA +test(0x1F6B, 0x1F63); // GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA, GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA +test(0x1F6C, 0x1F64); // GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA, GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA +test(0x1F6D, 0x1F65); // GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA, GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA +test(0x1F6E, 0x1F66); // GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI, GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI +test(0x1F6F, 0x1F67); // GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI, GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI +test(0x1F70, 0x1FBA); // GREEK SMALL LETTER ALPHA WITH VARIA, GREEK CAPITAL LETTER ALPHA WITH VARIA +test(0x1F71, 0x1FBB); // GREEK SMALL LETTER ALPHA WITH OXIA, GREEK CAPITAL LETTER ALPHA WITH OXIA +test(0x1F72, 0x1FC8); // GREEK SMALL LETTER EPSILON WITH VARIA, GREEK CAPITAL LETTER EPSILON WITH VARIA +test(0x1F73, 0x1FC9); // GREEK SMALL LETTER EPSILON WITH OXIA, GREEK CAPITAL LETTER EPSILON WITH OXIA +test(0x1F74, 0x1FCA); // GREEK SMALL LETTER ETA WITH VARIA, GREEK CAPITAL LETTER ETA WITH VARIA +test(0x1F75, 0x1FCB); // GREEK SMALL LETTER ETA WITH OXIA, GREEK CAPITAL LETTER ETA WITH OXIA +test(0x1F76, 0x1FDA); // GREEK SMALL LETTER IOTA WITH VARIA, GREEK CAPITAL LETTER IOTA WITH VARIA +test(0x1F77, 0x1FDB); // GREEK SMALL LETTER IOTA WITH OXIA, GREEK CAPITAL LETTER IOTA WITH OXIA +test(0x1F78, 0x1FF8); // GREEK SMALL LETTER OMICRON WITH VARIA, GREEK CAPITAL LETTER OMICRON WITH VARIA +test(0x1F79, 0x1FF9); // GREEK SMALL LETTER OMICRON WITH OXIA, GREEK CAPITAL LETTER OMICRON WITH OXIA +test(0x1F7A, 0x1FEA); // GREEK SMALL LETTER UPSILON WITH VARIA, GREEK CAPITAL LETTER UPSILON WITH VARIA +test(0x1F7B, 0x1FEB); // GREEK SMALL LETTER UPSILON WITH OXIA, GREEK CAPITAL LETTER UPSILON WITH OXIA +test(0x1F7C, 0x1FFA); // GREEK SMALL LETTER OMEGA WITH VARIA, GREEK CAPITAL LETTER OMEGA WITH VARIA +test(0x1F7D, 0x1FFB); // GREEK SMALL LETTER OMEGA WITH OXIA, GREEK CAPITAL LETTER OMEGA WITH OXIA +test(0x1F80, 0x1F88); // GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI, GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI +test(0x1F81, 0x1F89); // GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI, GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI +test(0x1F82, 0x1F8A); // GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI, GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI +test(0x1F83, 0x1F8B); // GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI, GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI +test(0x1F84, 0x1F8C); // GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI, GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI +test(0x1F85, 0x1F8D); // GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI, GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI +test(0x1F86, 0x1F8E); // GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI, GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI +test(0x1F87, 0x1F8F); // GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI, GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI +test(0x1F88, 0x1F80); // GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI, GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI +test(0x1F89, 0x1F81); // GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI, GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI +test(0x1F8A, 0x1F82); // GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI, GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI +test(0x1F8B, 0x1F83); // GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI, GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI +test(0x1F8C, 0x1F84); // GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI, GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI +test(0x1F8D, 0x1F85); // GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI, GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI +test(0x1F8E, 0x1F86); // GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI, GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI +test(0x1F8F, 0x1F87); // GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI, GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI +test(0x1F90, 0x1F98); // GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI, GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI +test(0x1F91, 0x1F99); // GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI, GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI +test(0x1F92, 0x1F9A); // GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI, GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI +test(0x1F93, 0x1F9B); // GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI, GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI +test(0x1F94, 0x1F9C); // GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI, GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI +test(0x1F95, 0x1F9D); // GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI, GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI +test(0x1F96, 0x1F9E); // GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI, GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI +test(0x1F97, 0x1F9F); // GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI, GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI +test(0x1F98, 0x1F90); // GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI, GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI +test(0x1F99, 0x1F91); // GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI, GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI +test(0x1F9A, 0x1F92); // GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI, GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI +test(0x1F9B, 0x1F93); // GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI, GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI +test(0x1F9C, 0x1F94); // GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI, GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI +test(0x1F9D, 0x1F95); // GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI, GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI +test(0x1F9E, 0x1F96); // GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI, GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI +test(0x1F9F, 0x1F97); // GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI, GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI +test(0x1FA0, 0x1FA8); // GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI, GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI +test(0x1FA1, 0x1FA9); // GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI, GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI +test(0x1FA2, 0x1FAA); // GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI, GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI +test(0x1FA3, 0x1FAB); // GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI, GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI +test(0x1FA4, 0x1FAC); // GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI, GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI +test(0x1FA5, 0x1FAD); // GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI, GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI +test(0x1FA6, 0x1FAE); // GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI, GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI +test(0x1FA7, 0x1FAF); // GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI, GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI +test(0x1FA8, 0x1FA0); // GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI, GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI +test(0x1FA9, 0x1FA1); // GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI, GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI +test(0x1FAA, 0x1FA2); // GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI, GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI +test(0x1FAB, 0x1FA3); // GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI, GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI +test(0x1FAC, 0x1FA4); // GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI, GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI +test(0x1FAD, 0x1FA5); // GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI, GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI +test(0x1FAE, 0x1FA6); // GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI, GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI +test(0x1FAF, 0x1FA7); // GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI, GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI +test(0x1FB0, 0x1FB8); // GREEK SMALL LETTER ALPHA WITH VRACHY, GREEK CAPITAL LETTER ALPHA WITH VRACHY +test(0x1FB1, 0x1FB9); // GREEK SMALL LETTER ALPHA WITH MACRON, GREEK CAPITAL LETTER ALPHA WITH MACRON +test(0x1FB3, 0x1FBC); // GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI, GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI +test(0x1FB8, 0x1FB0); // GREEK CAPITAL LETTER ALPHA WITH VRACHY, GREEK SMALL LETTER ALPHA WITH VRACHY +test(0x1FB9, 0x1FB1); // GREEK CAPITAL LETTER ALPHA WITH MACRON, GREEK SMALL LETTER ALPHA WITH MACRON +test(0x1FBA, 0x1F70); // GREEK CAPITAL LETTER ALPHA WITH VARIA, GREEK SMALL LETTER ALPHA WITH VARIA +test(0x1FBB, 0x1F71); // GREEK CAPITAL LETTER ALPHA WITH OXIA, GREEK SMALL LETTER ALPHA WITH OXIA +test(0x1FBC, 0x1FB3); // GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI, GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI +test(0x1FBE, 0x03B9, 0x0345, 0x0399); // GREEK PROSGEGRAMMENI, GREEK SMALL LETTER IOTA, COMBINING GREEK YPOGEGRAMMENI (GREEK NON-SPACING IOTA BELOW), GREEK CAPITAL LETTER IOTA +test(0x1FC3, 0x1FCC); // GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI, GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI +test(0x1FC8, 0x1F72); // GREEK CAPITAL LETTER EPSILON WITH VARIA, GREEK SMALL LETTER EPSILON WITH VARIA +test(0x1FC9, 0x1F73); // GREEK CAPITAL LETTER EPSILON WITH OXIA, GREEK SMALL LETTER EPSILON WITH OXIA +test(0x1FCA, 0x1F74); // GREEK CAPITAL LETTER ETA WITH VARIA, GREEK SMALL LETTER ETA WITH VARIA +test(0x1FCB, 0x1F75); // GREEK CAPITAL LETTER ETA WITH OXIA, GREEK SMALL LETTER ETA WITH OXIA +test(0x1FCC, 0x1FC3); // GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI, GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI +test(0x1FD0, 0x1FD8); // GREEK SMALL LETTER IOTA WITH VRACHY, GREEK CAPITAL LETTER IOTA WITH VRACHY +test(0x1FD1, 0x1FD9); // GREEK SMALL LETTER IOTA WITH MACRON, GREEK CAPITAL LETTER IOTA WITH MACRON +test(0x1FD8, 0x1FD0); // GREEK CAPITAL LETTER IOTA WITH VRACHY, GREEK SMALL LETTER IOTA WITH VRACHY +test(0x1FD9, 0x1FD1); // GREEK CAPITAL LETTER IOTA WITH MACRON, GREEK SMALL LETTER IOTA WITH MACRON +test(0x1FDA, 0x1F76); // GREEK CAPITAL LETTER IOTA WITH VARIA, GREEK SMALL LETTER IOTA WITH VARIA +test(0x1FDB, 0x1F77); // GREEK CAPITAL LETTER IOTA WITH OXIA, GREEK SMALL LETTER IOTA WITH OXIA +test(0x1FE0, 0x1FE8); // GREEK SMALL LETTER UPSILON WITH VRACHY, GREEK CAPITAL LETTER UPSILON WITH VRACHY +test(0x1FE1, 0x1FE9); // GREEK SMALL LETTER UPSILON WITH MACRON, GREEK CAPITAL LETTER UPSILON WITH MACRON +test(0x1FE5, 0x1FEC); // GREEK SMALL LETTER RHO WITH DASIA, GREEK CAPITAL LETTER RHO WITH DASIA +test(0x1FE8, 0x1FE0); // GREEK CAPITAL LETTER UPSILON WITH VRACHY, GREEK SMALL LETTER UPSILON WITH VRACHY +test(0x1FE9, 0x1FE1); // GREEK CAPITAL LETTER UPSILON WITH MACRON, GREEK SMALL LETTER UPSILON WITH MACRON +test(0x1FEA, 0x1F7A); // GREEK CAPITAL LETTER UPSILON WITH VARIA, GREEK SMALL LETTER UPSILON WITH VARIA +test(0x1FEB, 0x1F7B); // GREEK CAPITAL LETTER UPSILON WITH OXIA, GREEK SMALL LETTER UPSILON WITH OXIA +test(0x1FEC, 0x1FE5); // GREEK CAPITAL LETTER RHO WITH DASIA, GREEK SMALL LETTER RHO WITH DASIA +test(0x1FF3, 0x1FFC); // GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI, GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI +test(0x1FF8, 0x1F78); // GREEK CAPITAL LETTER OMICRON WITH VARIA, GREEK SMALL LETTER OMICRON WITH VARIA +test(0x1FF9, 0x1F79); // GREEK CAPITAL LETTER OMICRON WITH OXIA, GREEK SMALL LETTER OMICRON WITH OXIA +test(0x1FFA, 0x1F7C); // GREEK CAPITAL LETTER OMEGA WITH VARIA, GREEK SMALL LETTER OMEGA WITH VARIA +test(0x1FFB, 0x1F7D); // GREEK CAPITAL LETTER OMEGA WITH OXIA, GREEK SMALL LETTER OMEGA WITH OXIA +test(0x1FFC, 0x1FF3); // GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI, GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI +test(0x2126, 0x03C9, 0x03A9); // OHM SIGN (OHM), GREEK SMALL LETTER OMEGA, GREEK CAPITAL LETTER OMEGA +test(0x212A, 0x006B, 0x004B); // KELVIN SIGN (DEGREES KELVIN), LATIN SMALL LETTER K, LATIN CAPITAL LETTER K +test(0x212B, 0x00E5, 0x00C5); // ANGSTROM SIGN (ANGSTROM UNIT), LATIN SMALL LETTER A WITH RING ABOVE (LATIN SMALL LETTER A RING), LATIN CAPITAL LETTER A WITH RING ABOVE (LATIN CAPITAL LETTER A RING) +test(0x2132, 0x214E); // TURNED CAPITAL F (TURNED F), TURNED SMALL F +test(0x214E, 0x2132); // TURNED SMALL F, TURNED CAPITAL F (TURNED F) +test(0x2160, 0x2170); // ROMAN NUMERAL ONE, SMALL ROMAN NUMERAL ONE +test(0x2161, 0x2171); // ROMAN NUMERAL TWO, SMALL ROMAN NUMERAL TWO +test(0x2162, 0x2172); // ROMAN NUMERAL THREE, SMALL ROMAN NUMERAL THREE +test(0x2163, 0x2173); // ROMAN NUMERAL FOUR, SMALL ROMAN NUMERAL FOUR +test(0x2164, 0x2174); // ROMAN NUMERAL FIVE, SMALL ROMAN NUMERAL FIVE +test(0x2165, 0x2175); // ROMAN NUMERAL SIX, SMALL ROMAN NUMERAL SIX +test(0x2166, 0x2176); // ROMAN NUMERAL SEVEN, SMALL ROMAN NUMERAL SEVEN +test(0x2167, 0x2177); // ROMAN NUMERAL EIGHT, SMALL ROMAN NUMERAL EIGHT +test(0x2168, 0x2178); // ROMAN NUMERAL NINE, SMALL ROMAN NUMERAL NINE +test(0x2169, 0x2179); // ROMAN NUMERAL TEN, SMALL ROMAN NUMERAL TEN +test(0x216A, 0x217A); // ROMAN NUMERAL ELEVEN, SMALL ROMAN NUMERAL ELEVEN +test(0x216B, 0x217B); // ROMAN NUMERAL TWELVE, SMALL ROMAN NUMERAL TWELVE +test(0x216C, 0x217C); // ROMAN NUMERAL FIFTY, SMALL ROMAN NUMERAL FIFTY +test(0x216D, 0x217D); // ROMAN NUMERAL ONE HUNDRED, SMALL ROMAN NUMERAL ONE HUNDRED +test(0x216E, 0x217E); // ROMAN NUMERAL FIVE HUNDRED, SMALL ROMAN NUMERAL FIVE HUNDRED +test(0x216F, 0x217F); // ROMAN NUMERAL ONE THOUSAND, SMALL ROMAN NUMERAL ONE THOUSAND +test(0x2170, 0x2160); // SMALL ROMAN NUMERAL ONE, ROMAN NUMERAL ONE +test(0x2171, 0x2161); // SMALL ROMAN NUMERAL TWO, ROMAN NUMERAL TWO +test(0x2172, 0x2162); // SMALL ROMAN NUMERAL THREE, ROMAN NUMERAL THREE +test(0x2173, 0x2163); // SMALL ROMAN NUMERAL FOUR, ROMAN NUMERAL FOUR +test(0x2174, 0x2164); // SMALL ROMAN NUMERAL FIVE, ROMAN NUMERAL FIVE +test(0x2175, 0x2165); // SMALL ROMAN NUMERAL SIX, ROMAN NUMERAL SIX +test(0x2176, 0x2166); // SMALL ROMAN NUMERAL SEVEN, ROMAN NUMERAL SEVEN +test(0x2177, 0x2167); // SMALL ROMAN NUMERAL EIGHT, ROMAN NUMERAL EIGHT +test(0x2178, 0x2168); // SMALL ROMAN NUMERAL NINE, ROMAN NUMERAL NINE +test(0x2179, 0x2169); // SMALL ROMAN NUMERAL TEN, ROMAN NUMERAL TEN +test(0x217A, 0x216A); // SMALL ROMAN NUMERAL ELEVEN, ROMAN NUMERAL ELEVEN +test(0x217B, 0x216B); // SMALL ROMAN NUMERAL TWELVE, ROMAN NUMERAL TWELVE +test(0x217C, 0x216C); // SMALL ROMAN NUMERAL FIFTY, ROMAN NUMERAL FIFTY +test(0x217D, 0x216D); // SMALL ROMAN NUMERAL ONE HUNDRED, ROMAN NUMERAL ONE HUNDRED +test(0x217E, 0x216E); // SMALL ROMAN NUMERAL FIVE HUNDRED, ROMAN NUMERAL FIVE HUNDRED +test(0x217F, 0x216F); // SMALL ROMAN NUMERAL ONE THOUSAND, ROMAN NUMERAL ONE THOUSAND +test(0x2183, 0x2184); // ROMAN NUMERAL REVERSED ONE HUNDRED, LATIN SMALL LETTER REVERSED C +test(0x2184, 0x2183); // LATIN SMALL LETTER REVERSED C, ROMAN NUMERAL REVERSED ONE HUNDRED +test(0x24B6, 0x24D0); // CIRCLED LATIN CAPITAL LETTER A, CIRCLED LATIN SMALL LETTER A +test(0x24B7, 0x24D1); // CIRCLED LATIN CAPITAL LETTER B, CIRCLED LATIN SMALL LETTER B +test(0x24B8, 0x24D2); // CIRCLED LATIN CAPITAL LETTER C, CIRCLED LATIN SMALL LETTER C +test(0x24B9, 0x24D3); // CIRCLED LATIN CAPITAL LETTER D, CIRCLED LATIN SMALL LETTER D +test(0x24BA, 0x24D4); // CIRCLED LATIN CAPITAL LETTER E, CIRCLED LATIN SMALL LETTER E +test(0x24BB, 0x24D5); // CIRCLED LATIN CAPITAL LETTER F, CIRCLED LATIN SMALL LETTER F +test(0x24BC, 0x24D6); // CIRCLED LATIN CAPITAL LETTER G, CIRCLED LATIN SMALL LETTER G +test(0x24BD, 0x24D7); // CIRCLED LATIN CAPITAL LETTER H, CIRCLED LATIN SMALL LETTER H +test(0x24BE, 0x24D8); // CIRCLED LATIN CAPITAL LETTER I, CIRCLED LATIN SMALL LETTER I +test(0x24BF, 0x24D9); // CIRCLED LATIN CAPITAL LETTER J, CIRCLED LATIN SMALL LETTER J +test(0x24C0, 0x24DA); // CIRCLED LATIN CAPITAL LETTER K, CIRCLED LATIN SMALL LETTER K +test(0x24C1, 0x24DB); // CIRCLED LATIN CAPITAL LETTER L, CIRCLED LATIN SMALL LETTER L +test(0x24C2, 0x24DC); // CIRCLED LATIN CAPITAL LETTER M, CIRCLED LATIN SMALL LETTER M +test(0x24C3, 0x24DD); // CIRCLED LATIN CAPITAL LETTER N, CIRCLED LATIN SMALL LETTER N +test(0x24C4, 0x24DE); // CIRCLED LATIN CAPITAL LETTER O, CIRCLED LATIN SMALL LETTER O +test(0x24C5, 0x24DF); // CIRCLED LATIN CAPITAL LETTER P, CIRCLED LATIN SMALL LETTER P +test(0x24C6, 0x24E0); // CIRCLED LATIN CAPITAL LETTER Q, CIRCLED LATIN SMALL LETTER Q +test(0x24C7, 0x24E1); // CIRCLED LATIN CAPITAL LETTER R, CIRCLED LATIN SMALL LETTER R +test(0x24C8, 0x24E2); // CIRCLED LATIN CAPITAL LETTER S, CIRCLED LATIN SMALL LETTER S +test(0x24C9, 0x24E3); // CIRCLED LATIN CAPITAL LETTER T, CIRCLED LATIN SMALL LETTER T +test(0x24CA, 0x24E4); // CIRCLED LATIN CAPITAL LETTER U, CIRCLED LATIN SMALL LETTER U +test(0x24CB, 0x24E5); // CIRCLED LATIN CAPITAL LETTER V, CIRCLED LATIN SMALL LETTER V +test(0x24CC, 0x24E6); // CIRCLED LATIN CAPITAL LETTER W, CIRCLED LATIN SMALL LETTER W +test(0x24CD, 0x24E7); // CIRCLED LATIN CAPITAL LETTER X, CIRCLED LATIN SMALL LETTER X +test(0x24CE, 0x24E8); // CIRCLED LATIN CAPITAL LETTER Y, CIRCLED LATIN SMALL LETTER Y +test(0x24CF, 0x24E9); // CIRCLED LATIN CAPITAL LETTER Z, CIRCLED LATIN SMALL LETTER Z +test(0x24D0, 0x24B6); // CIRCLED LATIN SMALL LETTER A, CIRCLED LATIN CAPITAL LETTER A +test(0x24D1, 0x24B7); // CIRCLED LATIN SMALL LETTER B, CIRCLED LATIN CAPITAL LETTER B +test(0x24D2, 0x24B8); // CIRCLED LATIN SMALL LETTER C, CIRCLED LATIN CAPITAL LETTER C +test(0x24D3, 0x24B9); // CIRCLED LATIN SMALL LETTER D, CIRCLED LATIN CAPITAL LETTER D +test(0x24D4, 0x24BA); // CIRCLED LATIN SMALL LETTER E, CIRCLED LATIN CAPITAL LETTER E +test(0x24D5, 0x24BB); // CIRCLED LATIN SMALL LETTER F, CIRCLED LATIN CAPITAL LETTER F +test(0x24D6, 0x24BC); // CIRCLED LATIN SMALL LETTER G, CIRCLED LATIN CAPITAL LETTER G +test(0x24D7, 0x24BD); // CIRCLED LATIN SMALL LETTER H, CIRCLED LATIN CAPITAL LETTER H +test(0x24D8, 0x24BE); // CIRCLED LATIN SMALL LETTER I, CIRCLED LATIN CAPITAL LETTER I +test(0x24D9, 0x24BF); // CIRCLED LATIN SMALL LETTER J, CIRCLED LATIN CAPITAL LETTER J +test(0x24DA, 0x24C0); // CIRCLED LATIN SMALL LETTER K, CIRCLED LATIN CAPITAL LETTER K +test(0x24DB, 0x24C1); // CIRCLED LATIN SMALL LETTER L, CIRCLED LATIN CAPITAL LETTER L +test(0x24DC, 0x24C2); // CIRCLED LATIN SMALL LETTER M, CIRCLED LATIN CAPITAL LETTER M +test(0x24DD, 0x24C3); // CIRCLED LATIN SMALL LETTER N, CIRCLED LATIN CAPITAL LETTER N +test(0x24DE, 0x24C4); // CIRCLED LATIN SMALL LETTER O, CIRCLED LATIN CAPITAL LETTER O +test(0x24DF, 0x24C5); // CIRCLED LATIN SMALL LETTER P, CIRCLED LATIN CAPITAL LETTER P +test(0x24E0, 0x24C6); // CIRCLED LATIN SMALL LETTER Q, CIRCLED LATIN CAPITAL LETTER Q +test(0x24E1, 0x24C7); // CIRCLED LATIN SMALL LETTER R, CIRCLED LATIN CAPITAL LETTER R +test(0x24E2, 0x24C8); // CIRCLED LATIN SMALL LETTER S, CIRCLED LATIN CAPITAL LETTER S +test(0x24E3, 0x24C9); // CIRCLED LATIN SMALL LETTER T, CIRCLED LATIN CAPITAL LETTER T +test(0x24E4, 0x24CA); // CIRCLED LATIN SMALL LETTER U, CIRCLED LATIN CAPITAL LETTER U +test(0x24E5, 0x24CB); // CIRCLED LATIN SMALL LETTER V, CIRCLED LATIN CAPITAL LETTER V +test(0x24E6, 0x24CC); // CIRCLED LATIN SMALL LETTER W, CIRCLED LATIN CAPITAL LETTER W +test(0x24E7, 0x24CD); // CIRCLED LATIN SMALL LETTER X, CIRCLED LATIN CAPITAL LETTER X +test(0x24E8, 0x24CE); // CIRCLED LATIN SMALL LETTER Y, CIRCLED LATIN CAPITAL LETTER Y +test(0x24E9, 0x24CF); // CIRCLED LATIN SMALL LETTER Z, CIRCLED LATIN CAPITAL LETTER Z +test(0x2C00, 0x2C30); // GLAGOLITIC CAPITAL LETTER AZU, GLAGOLITIC SMALL LETTER AZU +test(0x2C01, 0x2C31); // GLAGOLITIC CAPITAL LETTER BUKY, GLAGOLITIC SMALL LETTER BUKY +test(0x2C02, 0x2C32); // GLAGOLITIC CAPITAL LETTER VEDE, GLAGOLITIC SMALL LETTER VEDE +test(0x2C03, 0x2C33); // GLAGOLITIC CAPITAL LETTER GLAGOLI, GLAGOLITIC SMALL LETTER GLAGOLI +test(0x2C04, 0x2C34); // GLAGOLITIC CAPITAL LETTER DOBRO, GLAGOLITIC SMALL LETTER DOBRO +test(0x2C05, 0x2C35); // GLAGOLITIC CAPITAL LETTER YESTU, GLAGOLITIC SMALL LETTER YESTU +test(0x2C06, 0x2C36); // GLAGOLITIC CAPITAL LETTER ZHIVETE, GLAGOLITIC SMALL LETTER ZHIVETE +test(0x2C07, 0x2C37); // GLAGOLITIC CAPITAL LETTER DZELO, GLAGOLITIC SMALL LETTER DZELO +test(0x2C08, 0x2C38); // GLAGOLITIC CAPITAL LETTER ZEMLJA, GLAGOLITIC SMALL LETTER ZEMLJA +test(0x2C09, 0x2C39); // GLAGOLITIC CAPITAL LETTER IZHE, GLAGOLITIC SMALL LETTER IZHE +test(0x2C0A, 0x2C3A); // GLAGOLITIC CAPITAL LETTER INITIAL IZHE, GLAGOLITIC SMALL LETTER INITIAL IZHE +test(0x2C0B, 0x2C3B); // GLAGOLITIC CAPITAL LETTER I, GLAGOLITIC SMALL LETTER I +test(0x2C0C, 0x2C3C); // GLAGOLITIC CAPITAL LETTER DJERVI, GLAGOLITIC SMALL LETTER DJERVI +test(0x2C0D, 0x2C3D); // GLAGOLITIC CAPITAL LETTER KAKO, GLAGOLITIC SMALL LETTER KAKO +test(0x2C0E, 0x2C3E); // GLAGOLITIC CAPITAL LETTER LJUDIJE, GLAGOLITIC SMALL LETTER LJUDIJE +test(0x2C0F, 0x2C3F); // GLAGOLITIC CAPITAL LETTER MYSLITE, GLAGOLITIC SMALL LETTER MYSLITE +test(0x2C10, 0x2C40); // GLAGOLITIC CAPITAL LETTER NASHI, GLAGOLITIC SMALL LETTER NASHI +test(0x2C11, 0x2C41); // GLAGOLITIC CAPITAL LETTER ONU, GLAGOLITIC SMALL LETTER ONU +test(0x2C12, 0x2C42); // GLAGOLITIC CAPITAL LETTER POKOJI, GLAGOLITIC SMALL LETTER POKOJI +test(0x2C13, 0x2C43); // GLAGOLITIC CAPITAL LETTER RITSI, GLAGOLITIC SMALL LETTER RITSI +test(0x2C14, 0x2C44); // GLAGOLITIC CAPITAL LETTER SLOVO, GLAGOLITIC SMALL LETTER SLOVO +test(0x2C15, 0x2C45); // GLAGOLITIC CAPITAL LETTER TVRIDO, GLAGOLITIC SMALL LETTER TVRIDO +test(0x2C16, 0x2C46); // GLAGOLITIC CAPITAL LETTER UKU, GLAGOLITIC SMALL LETTER UKU +test(0x2C17, 0x2C47); // GLAGOLITIC CAPITAL LETTER FRITU, GLAGOLITIC SMALL LETTER FRITU +test(0x2C18, 0x2C48); // GLAGOLITIC CAPITAL LETTER HERU, GLAGOLITIC SMALL LETTER HERU +test(0x2C19, 0x2C49); // GLAGOLITIC CAPITAL LETTER OTU, GLAGOLITIC SMALL LETTER OTU +test(0x2C1A, 0x2C4A); // GLAGOLITIC CAPITAL LETTER PE, GLAGOLITIC SMALL LETTER PE +test(0x2C1B, 0x2C4B); // GLAGOLITIC CAPITAL LETTER SHTA, GLAGOLITIC SMALL LETTER SHTA +test(0x2C1C, 0x2C4C); // GLAGOLITIC CAPITAL LETTER TSI, GLAGOLITIC SMALL LETTER TSI +test(0x2C1D, 0x2C4D); // GLAGOLITIC CAPITAL LETTER CHRIVI, GLAGOLITIC SMALL LETTER CHRIVI +test(0x2C1E, 0x2C4E); // GLAGOLITIC CAPITAL LETTER SHA, GLAGOLITIC SMALL LETTER SHA +test(0x2C1F, 0x2C4F); // GLAGOLITIC CAPITAL LETTER YERU, GLAGOLITIC SMALL LETTER YERU +test(0x2C20, 0x2C50); // GLAGOLITIC CAPITAL LETTER YERI, GLAGOLITIC SMALL LETTER YERI +test(0x2C21, 0x2C51); // GLAGOLITIC CAPITAL LETTER YATI, GLAGOLITIC SMALL LETTER YATI +test(0x2C22, 0x2C52); // GLAGOLITIC CAPITAL LETTER SPIDERY HA, GLAGOLITIC SMALL LETTER SPIDERY HA +test(0x2C23, 0x2C53); // GLAGOLITIC CAPITAL LETTER YU, GLAGOLITIC SMALL LETTER YU +test(0x2C24, 0x2C54); // GLAGOLITIC CAPITAL LETTER SMALL YUS, GLAGOLITIC SMALL LETTER SMALL YUS +test(0x2C25, 0x2C55); // GLAGOLITIC CAPITAL LETTER SMALL YUS WITH TAIL, GLAGOLITIC SMALL LETTER SMALL YUS WITH TAIL +test(0x2C26, 0x2C56); // GLAGOLITIC CAPITAL LETTER YO, GLAGOLITIC SMALL LETTER YO +test(0x2C27, 0x2C57); // GLAGOLITIC CAPITAL LETTER IOTATED SMALL YUS, GLAGOLITIC SMALL LETTER IOTATED SMALL YUS +test(0x2C28, 0x2C58); // GLAGOLITIC CAPITAL LETTER BIG YUS, GLAGOLITIC SMALL LETTER BIG YUS +test(0x2C29, 0x2C59); // GLAGOLITIC CAPITAL LETTER IOTATED BIG YUS, GLAGOLITIC SMALL LETTER IOTATED BIG YUS +test(0x2C2A, 0x2C5A); // GLAGOLITIC CAPITAL LETTER FITA, GLAGOLITIC SMALL LETTER FITA +test(0x2C2B, 0x2C5B); // GLAGOLITIC CAPITAL LETTER IZHITSA, GLAGOLITIC SMALL LETTER IZHITSA +test(0x2C2C, 0x2C5C); // GLAGOLITIC CAPITAL LETTER SHTAPIC, GLAGOLITIC SMALL LETTER SHTAPIC +test(0x2C2D, 0x2C5D); // GLAGOLITIC CAPITAL LETTER TROKUTASTI A, GLAGOLITIC SMALL LETTER TROKUTASTI A +test(0x2C2E, 0x2C5E); // GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE, GLAGOLITIC SMALL LETTER LATINATE MYSLITE +test(0x2C2F, 0x2C5F); // GLAGOLITIC CAPITAL LETTER CAUDATE CHRIVI, GLAGOLITIC SMALL LETTER CAUDATE CHRIVI +test(0x2C30, 0x2C00); // GLAGOLITIC SMALL LETTER AZU, GLAGOLITIC CAPITAL LETTER AZU +test(0x2C31, 0x2C01); // GLAGOLITIC SMALL LETTER BUKY, GLAGOLITIC CAPITAL LETTER BUKY +test(0x2C32, 0x2C02); // GLAGOLITIC SMALL LETTER VEDE, GLAGOLITIC CAPITAL LETTER VEDE +test(0x2C33, 0x2C03); // GLAGOLITIC SMALL LETTER GLAGOLI, GLAGOLITIC CAPITAL LETTER GLAGOLI +test(0x2C34, 0x2C04); // GLAGOLITIC SMALL LETTER DOBRO, GLAGOLITIC CAPITAL LETTER DOBRO +test(0x2C35, 0x2C05); // GLAGOLITIC SMALL LETTER YESTU, GLAGOLITIC CAPITAL LETTER YESTU +test(0x2C36, 0x2C06); // GLAGOLITIC SMALL LETTER ZHIVETE, GLAGOLITIC CAPITAL LETTER ZHIVETE +test(0x2C37, 0x2C07); // GLAGOLITIC SMALL LETTER DZELO, GLAGOLITIC CAPITAL LETTER DZELO +test(0x2C38, 0x2C08); // GLAGOLITIC SMALL LETTER ZEMLJA, GLAGOLITIC CAPITAL LETTER ZEMLJA +test(0x2C39, 0x2C09); // GLAGOLITIC SMALL LETTER IZHE, GLAGOLITIC CAPITAL LETTER IZHE +test(0x2C3A, 0x2C0A); // GLAGOLITIC SMALL LETTER INITIAL IZHE, GLAGOLITIC CAPITAL LETTER INITIAL IZHE +test(0x2C3B, 0x2C0B); // GLAGOLITIC SMALL LETTER I, GLAGOLITIC CAPITAL LETTER I +test(0x2C3C, 0x2C0C); // GLAGOLITIC SMALL LETTER DJERVI, GLAGOLITIC CAPITAL LETTER DJERVI +test(0x2C3D, 0x2C0D); // GLAGOLITIC SMALL LETTER KAKO, GLAGOLITIC CAPITAL LETTER KAKO +test(0x2C3E, 0x2C0E); // GLAGOLITIC SMALL LETTER LJUDIJE, GLAGOLITIC CAPITAL LETTER LJUDIJE +test(0x2C3F, 0x2C0F); // GLAGOLITIC SMALL LETTER MYSLITE, GLAGOLITIC CAPITAL LETTER MYSLITE +test(0x2C40, 0x2C10); // GLAGOLITIC SMALL LETTER NASHI, GLAGOLITIC CAPITAL LETTER NASHI +test(0x2C41, 0x2C11); // GLAGOLITIC SMALL LETTER ONU, GLAGOLITIC CAPITAL LETTER ONU +test(0x2C42, 0x2C12); // GLAGOLITIC SMALL LETTER POKOJI, GLAGOLITIC CAPITAL LETTER POKOJI +test(0x2C43, 0x2C13); // GLAGOLITIC SMALL LETTER RITSI, GLAGOLITIC CAPITAL LETTER RITSI +test(0x2C44, 0x2C14); // GLAGOLITIC SMALL LETTER SLOVO, GLAGOLITIC CAPITAL LETTER SLOVO +test(0x2C45, 0x2C15); // GLAGOLITIC SMALL LETTER TVRIDO, GLAGOLITIC CAPITAL LETTER TVRIDO +test(0x2C46, 0x2C16); // GLAGOLITIC SMALL LETTER UKU, GLAGOLITIC CAPITAL LETTER UKU +test(0x2C47, 0x2C17); // GLAGOLITIC SMALL LETTER FRITU, GLAGOLITIC CAPITAL LETTER FRITU +test(0x2C48, 0x2C18); // GLAGOLITIC SMALL LETTER HERU, GLAGOLITIC CAPITAL LETTER HERU +test(0x2C49, 0x2C19); // GLAGOLITIC SMALL LETTER OTU, GLAGOLITIC CAPITAL LETTER OTU +test(0x2C4A, 0x2C1A); // GLAGOLITIC SMALL LETTER PE, GLAGOLITIC CAPITAL LETTER PE +test(0x2C4B, 0x2C1B); // GLAGOLITIC SMALL LETTER SHTA, GLAGOLITIC CAPITAL LETTER SHTA +test(0x2C4C, 0x2C1C); // GLAGOLITIC SMALL LETTER TSI, GLAGOLITIC CAPITAL LETTER TSI +test(0x2C4D, 0x2C1D); // GLAGOLITIC SMALL LETTER CHRIVI, GLAGOLITIC CAPITAL LETTER CHRIVI +test(0x2C4E, 0x2C1E); // GLAGOLITIC SMALL LETTER SHA, GLAGOLITIC CAPITAL LETTER SHA +test(0x2C4F, 0x2C1F); // GLAGOLITIC SMALL LETTER YERU, GLAGOLITIC CAPITAL LETTER YERU +test(0x2C50, 0x2C20); // GLAGOLITIC SMALL LETTER YERI, GLAGOLITIC CAPITAL LETTER YERI +test(0x2C51, 0x2C21); // GLAGOLITIC SMALL LETTER YATI, GLAGOLITIC CAPITAL LETTER YATI +test(0x2C52, 0x2C22); // GLAGOLITIC SMALL LETTER SPIDERY HA, GLAGOLITIC CAPITAL LETTER SPIDERY HA +test(0x2C53, 0x2C23); // GLAGOLITIC SMALL LETTER YU, GLAGOLITIC CAPITAL LETTER YU +test(0x2C54, 0x2C24); // GLAGOLITIC SMALL LETTER SMALL YUS, GLAGOLITIC CAPITAL LETTER SMALL YUS +test(0x2C55, 0x2C25); // GLAGOLITIC SMALL LETTER SMALL YUS WITH TAIL, GLAGOLITIC CAPITAL LETTER SMALL YUS WITH TAIL +test(0x2C56, 0x2C26); // GLAGOLITIC SMALL LETTER YO, GLAGOLITIC CAPITAL LETTER YO +test(0x2C57, 0x2C27); // GLAGOLITIC SMALL LETTER IOTATED SMALL YUS, GLAGOLITIC CAPITAL LETTER IOTATED SMALL YUS +test(0x2C58, 0x2C28); // GLAGOLITIC SMALL LETTER BIG YUS, GLAGOLITIC CAPITAL LETTER BIG YUS +test(0x2C59, 0x2C29); // GLAGOLITIC SMALL LETTER IOTATED BIG YUS, GLAGOLITIC CAPITAL LETTER IOTATED BIG YUS +test(0x2C5A, 0x2C2A); // GLAGOLITIC SMALL LETTER FITA, GLAGOLITIC CAPITAL LETTER FITA +test(0x2C5B, 0x2C2B); // GLAGOLITIC SMALL LETTER IZHITSA, GLAGOLITIC CAPITAL LETTER IZHITSA +test(0x2C5C, 0x2C2C); // GLAGOLITIC SMALL LETTER SHTAPIC, GLAGOLITIC CAPITAL LETTER SHTAPIC +test(0x2C5D, 0x2C2D); // GLAGOLITIC SMALL LETTER TROKUTASTI A, GLAGOLITIC CAPITAL LETTER TROKUTASTI A +test(0x2C5E, 0x2C2E); // GLAGOLITIC SMALL LETTER LATINATE MYSLITE, GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE +test(0x2C5F, 0x2C2F); // GLAGOLITIC SMALL LETTER CAUDATE CHRIVI, GLAGOLITIC CAPITAL LETTER CAUDATE CHRIVI +test(0x2C60, 0x2C61); // LATIN CAPITAL LETTER L WITH DOUBLE BAR, LATIN SMALL LETTER L WITH DOUBLE BAR +test(0x2C61, 0x2C60); // LATIN SMALL LETTER L WITH DOUBLE BAR, LATIN CAPITAL LETTER L WITH DOUBLE BAR +test(0x2C62, 0x026B); // LATIN CAPITAL LETTER L WITH MIDDLE TILDE, LATIN SMALL LETTER L WITH MIDDLE TILDE +test(0x2C63, 0x1D7D); // LATIN CAPITAL LETTER P WITH STROKE, LATIN SMALL LETTER P WITH STROKE +test(0x2C64, 0x027D); // LATIN CAPITAL LETTER R WITH TAIL, LATIN SMALL LETTER R WITH TAIL (LATIN SMALL LETTER R HOOK) +test(0x2C65, 0x023A); // LATIN SMALL LETTER A WITH STROKE, LATIN CAPITAL LETTER A WITH STROKE +test(0x2C66, 0x023E); // LATIN SMALL LETTER T WITH DIAGONAL STROKE, LATIN CAPITAL LETTER T WITH DIAGONAL STROKE +test(0x2C67, 0x2C68); // LATIN CAPITAL LETTER H WITH DESCENDER, LATIN SMALL LETTER H WITH DESCENDER +test(0x2C68, 0x2C67); // LATIN SMALL LETTER H WITH DESCENDER, LATIN CAPITAL LETTER H WITH DESCENDER +test(0x2C69, 0x2C6A); // LATIN CAPITAL LETTER K WITH DESCENDER, LATIN SMALL LETTER K WITH DESCENDER +test(0x2C6A, 0x2C69); // LATIN SMALL LETTER K WITH DESCENDER, LATIN CAPITAL LETTER K WITH DESCENDER +test(0x2C6B, 0x2C6C); // LATIN CAPITAL LETTER Z WITH DESCENDER, LATIN SMALL LETTER Z WITH DESCENDER +test(0x2C6C, 0x2C6B); // LATIN SMALL LETTER Z WITH DESCENDER, LATIN CAPITAL LETTER Z WITH DESCENDER +test(0x2C6D, 0x0251); // LATIN CAPITAL LETTER ALPHA, LATIN SMALL LETTER ALPHA (LATIN SMALL LETTER SCRIPT A) +test(0x2C6E, 0x0271); // LATIN CAPITAL LETTER M WITH HOOK, LATIN SMALL LETTER M WITH HOOK (LATIN SMALL LETTER M HOOK) +test(0x2C6F, 0x0250); // LATIN CAPITAL LETTER TURNED A, LATIN SMALL LETTER TURNED A +test(0x2C70, 0x0252); // LATIN CAPITAL LETTER TURNED ALPHA, LATIN SMALL LETTER TURNED ALPHA (LATIN SMALL LETTER TURNED SCRIPT A) +test(0x2C72, 0x2C73); // LATIN CAPITAL LETTER W WITH HOOK, LATIN SMALL LETTER W WITH HOOK +test(0x2C73, 0x2C72); // LATIN SMALL LETTER W WITH HOOK, LATIN CAPITAL LETTER W WITH HOOK +test(0x2C75, 0x2C76); // LATIN CAPITAL LETTER HALF H, LATIN SMALL LETTER HALF H +test(0x2C76, 0x2C75); // LATIN SMALL LETTER HALF H, LATIN CAPITAL LETTER HALF H +test(0x2C7E, 0x023F); // LATIN CAPITAL LETTER S WITH SWASH TAIL, LATIN SMALL LETTER S WITH SWASH TAIL +test(0x2C7F, 0x0240); // LATIN CAPITAL LETTER Z WITH SWASH TAIL, LATIN SMALL LETTER Z WITH SWASH TAIL +test(0x2C80, 0x2C81); // COPTIC CAPITAL LETTER ALFA, COPTIC SMALL LETTER ALFA +test(0x2C81, 0x2C80); // COPTIC SMALL LETTER ALFA, COPTIC CAPITAL LETTER ALFA +test(0x2C82, 0x2C83); // COPTIC CAPITAL LETTER VIDA, COPTIC SMALL LETTER VIDA +test(0x2C83, 0x2C82); // COPTIC SMALL LETTER VIDA, COPTIC CAPITAL LETTER VIDA +test(0x2C84, 0x2C85); // COPTIC CAPITAL LETTER GAMMA, COPTIC SMALL LETTER GAMMA +test(0x2C85, 0x2C84); // COPTIC SMALL LETTER GAMMA, COPTIC CAPITAL LETTER GAMMA +test(0x2C86, 0x2C87); // COPTIC CAPITAL LETTER DALDA, COPTIC SMALL LETTER DALDA +test(0x2C87, 0x2C86); // COPTIC SMALL LETTER DALDA, COPTIC CAPITAL LETTER DALDA +test(0x2C88, 0x2C89); // COPTIC CAPITAL LETTER EIE, COPTIC SMALL LETTER EIE +test(0x2C89, 0x2C88); // COPTIC SMALL LETTER EIE, COPTIC CAPITAL LETTER EIE +test(0x2C8A, 0x2C8B); // COPTIC CAPITAL LETTER SOU, COPTIC SMALL LETTER SOU +test(0x2C8B, 0x2C8A); // COPTIC SMALL LETTER SOU, COPTIC CAPITAL LETTER SOU +test(0x2C8C, 0x2C8D); // COPTIC CAPITAL LETTER ZATA, COPTIC SMALL LETTER ZATA +test(0x2C8D, 0x2C8C); // COPTIC SMALL LETTER ZATA, COPTIC CAPITAL LETTER ZATA +test(0x2C8E, 0x2C8F); // COPTIC CAPITAL LETTER HATE, COPTIC SMALL LETTER HATE +test(0x2C8F, 0x2C8E); // COPTIC SMALL LETTER HATE, COPTIC CAPITAL LETTER HATE +test(0x2C90, 0x2C91); // COPTIC CAPITAL LETTER THETHE, COPTIC SMALL LETTER THETHE +test(0x2C91, 0x2C90); // COPTIC SMALL LETTER THETHE, COPTIC CAPITAL LETTER THETHE +test(0x2C92, 0x2C93); // COPTIC CAPITAL LETTER IAUDA, COPTIC SMALL LETTER IAUDA +test(0x2C93, 0x2C92); // COPTIC SMALL LETTER IAUDA, COPTIC CAPITAL LETTER IAUDA +test(0x2C94, 0x2C95); // COPTIC CAPITAL LETTER KAPA, COPTIC SMALL LETTER KAPA +test(0x2C95, 0x2C94); // COPTIC SMALL LETTER KAPA, COPTIC CAPITAL LETTER KAPA +test(0x2C96, 0x2C97); // COPTIC CAPITAL LETTER LAULA, COPTIC SMALL LETTER LAULA +test(0x2C97, 0x2C96); // COPTIC SMALL LETTER LAULA, COPTIC CAPITAL LETTER LAULA +test(0x2C98, 0x2C99); // COPTIC CAPITAL LETTER MI, COPTIC SMALL LETTER MI +test(0x2C99, 0x2C98); // COPTIC SMALL LETTER MI, COPTIC CAPITAL LETTER MI +test(0x2C9A, 0x2C9B); // COPTIC CAPITAL LETTER NI, COPTIC SMALL LETTER NI +test(0x2C9B, 0x2C9A); // COPTIC SMALL LETTER NI, COPTIC CAPITAL LETTER NI +test(0x2C9C, 0x2C9D); // COPTIC CAPITAL LETTER KSI, COPTIC SMALL LETTER KSI +test(0x2C9D, 0x2C9C); // COPTIC SMALL LETTER KSI, COPTIC CAPITAL LETTER KSI +test(0x2C9E, 0x2C9F); // COPTIC CAPITAL LETTER O, COPTIC SMALL LETTER O +test(0x2C9F, 0x2C9E); // COPTIC SMALL LETTER O, COPTIC CAPITAL LETTER O +test(0x2CA0, 0x2CA1); // COPTIC CAPITAL LETTER PI, COPTIC SMALL LETTER PI +test(0x2CA1, 0x2CA0); // COPTIC SMALL LETTER PI, COPTIC CAPITAL LETTER PI +test(0x2CA2, 0x2CA3); // COPTIC CAPITAL LETTER RO, COPTIC SMALL LETTER RO +test(0x2CA3, 0x2CA2); // COPTIC SMALL LETTER RO, COPTIC CAPITAL LETTER RO +test(0x2CA4, 0x2CA5); // COPTIC CAPITAL LETTER SIMA, COPTIC SMALL LETTER SIMA +test(0x2CA5, 0x2CA4); // COPTIC SMALL LETTER SIMA, COPTIC CAPITAL LETTER SIMA +test(0x2CA6, 0x2CA7); // COPTIC CAPITAL LETTER TAU, COPTIC SMALL LETTER TAU +test(0x2CA7, 0x2CA6); // COPTIC SMALL LETTER TAU, COPTIC CAPITAL LETTER TAU +test(0x2CA8, 0x2CA9); // COPTIC CAPITAL LETTER UA, COPTIC SMALL LETTER UA +test(0x2CA9, 0x2CA8); // COPTIC SMALL LETTER UA, COPTIC CAPITAL LETTER UA +test(0x2CAA, 0x2CAB); // COPTIC CAPITAL LETTER FI, COPTIC SMALL LETTER FI +test(0x2CAB, 0x2CAA); // COPTIC SMALL LETTER FI, COPTIC CAPITAL LETTER FI +test(0x2CAC, 0x2CAD); // COPTIC CAPITAL LETTER KHI, COPTIC SMALL LETTER KHI +test(0x2CAD, 0x2CAC); // COPTIC SMALL LETTER KHI, COPTIC CAPITAL LETTER KHI +test(0x2CAE, 0x2CAF); // COPTIC CAPITAL LETTER PSI, COPTIC SMALL LETTER PSI +test(0x2CAF, 0x2CAE); // COPTIC SMALL LETTER PSI, COPTIC CAPITAL LETTER PSI +test(0x2CB0, 0x2CB1); // COPTIC CAPITAL LETTER OOU, COPTIC SMALL LETTER OOU +test(0x2CB1, 0x2CB0); // COPTIC SMALL LETTER OOU, COPTIC CAPITAL LETTER OOU +test(0x2CB2, 0x2CB3); // COPTIC CAPITAL LETTER DIALECT-P ALEF, COPTIC SMALL LETTER DIALECT-P ALEF +test(0x2CB3, 0x2CB2); // COPTIC SMALL LETTER DIALECT-P ALEF, COPTIC CAPITAL LETTER DIALECT-P ALEF +test(0x2CB4, 0x2CB5); // COPTIC CAPITAL LETTER OLD COPTIC AIN, COPTIC SMALL LETTER OLD COPTIC AIN +test(0x2CB5, 0x2CB4); // COPTIC SMALL LETTER OLD COPTIC AIN, COPTIC CAPITAL LETTER OLD COPTIC AIN +test(0x2CB6, 0x2CB7); // COPTIC CAPITAL LETTER CRYPTOGRAMMIC EIE, COPTIC SMALL LETTER CRYPTOGRAMMIC EIE +test(0x2CB7, 0x2CB6); // COPTIC SMALL LETTER CRYPTOGRAMMIC EIE, COPTIC CAPITAL LETTER CRYPTOGRAMMIC EIE +test(0x2CB8, 0x2CB9); // COPTIC CAPITAL LETTER DIALECT-P KAPA, COPTIC SMALL LETTER DIALECT-P KAPA +test(0x2CB9, 0x2CB8); // COPTIC SMALL LETTER DIALECT-P KAPA, COPTIC CAPITAL LETTER DIALECT-P KAPA +test(0x2CBA, 0x2CBB); // COPTIC CAPITAL LETTER DIALECT-P NI, COPTIC SMALL LETTER DIALECT-P NI +test(0x2CBB, 0x2CBA); // COPTIC SMALL LETTER DIALECT-P NI, COPTIC CAPITAL LETTER DIALECT-P NI +test(0x2CBC, 0x2CBD); // COPTIC CAPITAL LETTER CRYPTOGRAMMIC NI, COPTIC SMALL LETTER CRYPTOGRAMMIC NI +test(0x2CBD, 0x2CBC); // COPTIC SMALL LETTER CRYPTOGRAMMIC NI, COPTIC CAPITAL LETTER CRYPTOGRAMMIC NI +test(0x2CBE, 0x2CBF); // COPTIC CAPITAL LETTER OLD COPTIC OOU, COPTIC SMALL LETTER OLD COPTIC OOU +test(0x2CBF, 0x2CBE); // COPTIC SMALL LETTER OLD COPTIC OOU, COPTIC CAPITAL LETTER OLD COPTIC OOU +test(0x2CC0, 0x2CC1); // COPTIC CAPITAL LETTER SAMPI, COPTIC SMALL LETTER SAMPI +test(0x2CC1, 0x2CC0); // COPTIC SMALL LETTER SAMPI, COPTIC CAPITAL LETTER SAMPI +test(0x2CC2, 0x2CC3); // COPTIC CAPITAL LETTER CROSSED SHEI, COPTIC SMALL LETTER CROSSED SHEI +test(0x2CC3, 0x2CC2); // COPTIC SMALL LETTER CROSSED SHEI, COPTIC CAPITAL LETTER CROSSED SHEI +test(0x2CC4, 0x2CC5); // COPTIC CAPITAL LETTER OLD COPTIC SHEI, COPTIC SMALL LETTER OLD COPTIC SHEI +test(0x2CC5, 0x2CC4); // COPTIC SMALL LETTER OLD COPTIC SHEI, COPTIC CAPITAL LETTER OLD COPTIC SHEI +test(0x2CC6, 0x2CC7); // COPTIC CAPITAL LETTER OLD COPTIC ESH, COPTIC SMALL LETTER OLD COPTIC ESH +test(0x2CC7, 0x2CC6); // COPTIC SMALL LETTER OLD COPTIC ESH, COPTIC CAPITAL LETTER OLD COPTIC ESH +test(0x2CC8, 0x2CC9); // COPTIC CAPITAL LETTER AKHMIMIC KHEI, COPTIC SMALL LETTER AKHMIMIC KHEI +test(0x2CC9, 0x2CC8); // COPTIC SMALL LETTER AKHMIMIC KHEI, COPTIC CAPITAL LETTER AKHMIMIC KHEI +test(0x2CCA, 0x2CCB); // COPTIC CAPITAL LETTER DIALECT-P HORI, COPTIC SMALL LETTER DIALECT-P HORI +test(0x2CCB, 0x2CCA); // COPTIC SMALL LETTER DIALECT-P HORI, COPTIC CAPITAL LETTER DIALECT-P HORI +test(0x2CCC, 0x2CCD); // COPTIC CAPITAL LETTER OLD COPTIC HORI, COPTIC SMALL LETTER OLD COPTIC HORI +test(0x2CCD, 0x2CCC); // COPTIC SMALL LETTER OLD COPTIC HORI, COPTIC CAPITAL LETTER OLD COPTIC HORI +test(0x2CCE, 0x2CCF); // COPTIC CAPITAL LETTER OLD COPTIC HA, COPTIC SMALL LETTER OLD COPTIC HA +test(0x2CCF, 0x2CCE); // COPTIC SMALL LETTER OLD COPTIC HA, COPTIC CAPITAL LETTER OLD COPTIC HA +test(0x2CD0, 0x2CD1); // COPTIC CAPITAL LETTER L-SHAPED HA, COPTIC SMALL LETTER L-SHAPED HA +test(0x2CD1, 0x2CD0); // COPTIC SMALL LETTER L-SHAPED HA, COPTIC CAPITAL LETTER L-SHAPED HA +test(0x2CD2, 0x2CD3); // COPTIC CAPITAL LETTER OLD COPTIC HEI, COPTIC SMALL LETTER OLD COPTIC HEI +test(0x2CD3, 0x2CD2); // COPTIC SMALL LETTER OLD COPTIC HEI, COPTIC CAPITAL LETTER OLD COPTIC HEI +test(0x2CD4, 0x2CD5); // COPTIC CAPITAL LETTER OLD COPTIC HAT, COPTIC SMALL LETTER OLD COPTIC HAT +test(0x2CD5, 0x2CD4); // COPTIC SMALL LETTER OLD COPTIC HAT, COPTIC CAPITAL LETTER OLD COPTIC HAT +test(0x2CD6, 0x2CD7); // COPTIC CAPITAL LETTER OLD COPTIC GANGIA, COPTIC SMALL LETTER OLD COPTIC GANGIA +test(0x2CD7, 0x2CD6); // COPTIC SMALL LETTER OLD COPTIC GANGIA, COPTIC CAPITAL LETTER OLD COPTIC GANGIA +test(0x2CD8, 0x2CD9); // COPTIC CAPITAL LETTER OLD COPTIC DJA, COPTIC SMALL LETTER OLD COPTIC DJA +test(0x2CD9, 0x2CD8); // COPTIC SMALL LETTER OLD COPTIC DJA, COPTIC CAPITAL LETTER OLD COPTIC DJA +test(0x2CDA, 0x2CDB); // COPTIC CAPITAL LETTER OLD COPTIC SHIMA, COPTIC SMALL LETTER OLD COPTIC SHIMA +test(0x2CDB, 0x2CDA); // COPTIC SMALL LETTER OLD COPTIC SHIMA, COPTIC CAPITAL LETTER OLD COPTIC SHIMA +test(0x2CDC, 0x2CDD); // COPTIC CAPITAL LETTER OLD NUBIAN SHIMA, COPTIC SMALL LETTER OLD NUBIAN SHIMA +test(0x2CDD, 0x2CDC); // COPTIC SMALL LETTER OLD NUBIAN SHIMA, COPTIC CAPITAL LETTER OLD NUBIAN SHIMA +test(0x2CDE, 0x2CDF); // COPTIC CAPITAL LETTER OLD NUBIAN NGI, COPTIC SMALL LETTER OLD NUBIAN NGI +test(0x2CDF, 0x2CDE); // COPTIC SMALL LETTER OLD NUBIAN NGI, COPTIC CAPITAL LETTER OLD NUBIAN NGI +test(0x2CE0, 0x2CE1); // COPTIC CAPITAL LETTER OLD NUBIAN NYI, COPTIC SMALL LETTER OLD NUBIAN NYI +test(0x2CE1, 0x2CE0); // COPTIC SMALL LETTER OLD NUBIAN NYI, COPTIC CAPITAL LETTER OLD NUBIAN NYI +test(0x2CE2, 0x2CE3); // COPTIC CAPITAL LETTER OLD NUBIAN WAU, COPTIC SMALL LETTER OLD NUBIAN WAU +test(0x2CE3, 0x2CE2); // COPTIC SMALL LETTER OLD NUBIAN WAU, COPTIC CAPITAL LETTER OLD NUBIAN WAU +test(0x2CEB, 0x2CEC); // COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI, COPTIC SMALL LETTER CRYPTOGRAMMIC SHEI +test(0x2CEC, 0x2CEB); // COPTIC SMALL LETTER CRYPTOGRAMMIC SHEI, COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI +test(0x2CED, 0x2CEE); // COPTIC CAPITAL LETTER CRYPTOGRAMMIC GANGIA, COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA +test(0x2CEE, 0x2CED); // COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA, COPTIC CAPITAL LETTER CRYPTOGRAMMIC GANGIA +test(0x2CF2, 0x2CF3); // COPTIC CAPITAL LETTER BOHAIRIC KHEI, COPTIC SMALL LETTER BOHAIRIC KHEI +test(0x2CF3, 0x2CF2); // COPTIC SMALL LETTER BOHAIRIC KHEI, COPTIC CAPITAL LETTER BOHAIRIC KHEI +test(0x2D00, 0x10A0); // GEORGIAN SMALL LETTER AN, GEORGIAN CAPITAL LETTER AN +test(0x2D01, 0x10A1); // GEORGIAN SMALL LETTER BAN, GEORGIAN CAPITAL LETTER BAN +test(0x2D02, 0x10A2); // GEORGIAN SMALL LETTER GAN, GEORGIAN CAPITAL LETTER GAN +test(0x2D03, 0x10A3); // GEORGIAN SMALL LETTER DON, GEORGIAN CAPITAL LETTER DON +test(0x2D04, 0x10A4); // GEORGIAN SMALL LETTER EN, GEORGIAN CAPITAL LETTER EN +test(0x2D05, 0x10A5); // GEORGIAN SMALL LETTER VIN, GEORGIAN CAPITAL LETTER VIN +test(0x2D06, 0x10A6); // GEORGIAN SMALL LETTER ZEN, GEORGIAN CAPITAL LETTER ZEN +test(0x2D07, 0x10A7); // GEORGIAN SMALL LETTER TAN, GEORGIAN CAPITAL LETTER TAN +test(0x2D08, 0x10A8); // GEORGIAN SMALL LETTER IN, GEORGIAN CAPITAL LETTER IN +test(0x2D09, 0x10A9); // GEORGIAN SMALL LETTER KAN, GEORGIAN CAPITAL LETTER KAN +test(0x2D0A, 0x10AA); // GEORGIAN SMALL LETTER LAS, GEORGIAN CAPITAL LETTER LAS +test(0x2D0B, 0x10AB); // GEORGIAN SMALL LETTER MAN, GEORGIAN CAPITAL LETTER MAN +test(0x2D0C, 0x10AC); // GEORGIAN SMALL LETTER NAR, GEORGIAN CAPITAL LETTER NAR +test(0x2D0D, 0x10AD); // GEORGIAN SMALL LETTER ON, GEORGIAN CAPITAL LETTER ON +test(0x2D0E, 0x10AE); // GEORGIAN SMALL LETTER PAR, GEORGIAN CAPITAL LETTER PAR +test(0x2D0F, 0x10AF); // GEORGIAN SMALL LETTER ZHAR, GEORGIAN CAPITAL LETTER ZHAR +test(0x2D10, 0x10B0); // GEORGIAN SMALL LETTER RAE, GEORGIAN CAPITAL LETTER RAE +test(0x2D11, 0x10B1); // GEORGIAN SMALL LETTER SAN, GEORGIAN CAPITAL LETTER SAN +test(0x2D12, 0x10B2); // GEORGIAN SMALL LETTER TAR, GEORGIAN CAPITAL LETTER TAR +test(0x2D13, 0x10B3); // GEORGIAN SMALL LETTER UN, GEORGIAN CAPITAL LETTER UN +test(0x2D14, 0x10B4); // GEORGIAN SMALL LETTER PHAR, GEORGIAN CAPITAL LETTER PHAR +test(0x2D15, 0x10B5); // GEORGIAN SMALL LETTER KHAR, GEORGIAN CAPITAL LETTER KHAR +test(0x2D16, 0x10B6); // GEORGIAN SMALL LETTER GHAN, GEORGIAN CAPITAL LETTER GHAN +test(0x2D17, 0x10B7); // GEORGIAN SMALL LETTER QAR, GEORGIAN CAPITAL LETTER QAR +test(0x2D18, 0x10B8); // GEORGIAN SMALL LETTER SHIN, GEORGIAN CAPITAL LETTER SHIN +test(0x2D19, 0x10B9); // GEORGIAN SMALL LETTER CHIN, GEORGIAN CAPITAL LETTER CHIN +test(0x2D1A, 0x10BA); // GEORGIAN SMALL LETTER CAN, GEORGIAN CAPITAL LETTER CAN +test(0x2D1B, 0x10BB); // GEORGIAN SMALL LETTER JIL, GEORGIAN CAPITAL LETTER JIL +test(0x2D1C, 0x10BC); // GEORGIAN SMALL LETTER CIL, GEORGIAN CAPITAL LETTER CIL +test(0x2D1D, 0x10BD); // GEORGIAN SMALL LETTER CHAR, GEORGIAN CAPITAL LETTER CHAR +test(0x2D1E, 0x10BE); // GEORGIAN SMALL LETTER XAN, GEORGIAN CAPITAL LETTER XAN +test(0x2D1F, 0x10BF); // GEORGIAN SMALL LETTER JHAN, GEORGIAN CAPITAL LETTER JHAN +test(0x2D20, 0x10C0); // GEORGIAN SMALL LETTER HAE, GEORGIAN CAPITAL LETTER HAE +test(0x2D21, 0x10C1); // GEORGIAN SMALL LETTER HE, GEORGIAN CAPITAL LETTER HE +test(0x2D22, 0x10C2); // GEORGIAN SMALL LETTER HIE, GEORGIAN CAPITAL LETTER HIE +test(0x2D23, 0x10C3); // GEORGIAN SMALL LETTER WE, GEORGIAN CAPITAL LETTER WE +test(0x2D24, 0x10C4); // GEORGIAN SMALL LETTER HAR, GEORGIAN CAPITAL LETTER HAR +test(0x2D25, 0x10C5); // GEORGIAN SMALL LETTER HOE, GEORGIAN CAPITAL LETTER HOE +test(0x2D27, 0x10C7); // GEORGIAN SMALL LETTER YN, GEORGIAN CAPITAL LETTER YN +test(0x2D2D, 0x10CD); // GEORGIAN SMALL LETTER AEN, GEORGIAN CAPITAL LETTER AEN +test(0xA640, 0xA641); // CYRILLIC CAPITAL LETTER ZEMLYA, CYRILLIC SMALL LETTER ZEMLYA +test(0xA641, 0xA640); // CYRILLIC SMALL LETTER ZEMLYA, CYRILLIC CAPITAL LETTER ZEMLYA +test(0xA642, 0xA643); // CYRILLIC CAPITAL LETTER DZELO, CYRILLIC SMALL LETTER DZELO +test(0xA643, 0xA642); // CYRILLIC SMALL LETTER DZELO, CYRILLIC CAPITAL LETTER DZELO +test(0xA644, 0xA645); // CYRILLIC CAPITAL LETTER REVERSED DZE, CYRILLIC SMALL LETTER REVERSED DZE +test(0xA645, 0xA644); // CYRILLIC SMALL LETTER REVERSED DZE, CYRILLIC CAPITAL LETTER REVERSED DZE +test(0xA646, 0xA647); // CYRILLIC CAPITAL LETTER IOTA, CYRILLIC SMALL LETTER IOTA +test(0xA647, 0xA646); // CYRILLIC SMALL LETTER IOTA, CYRILLIC CAPITAL LETTER IOTA +test(0xA648, 0xA649); // CYRILLIC CAPITAL LETTER DJERV, CYRILLIC SMALL LETTER DJERV +test(0xA649, 0xA648); // CYRILLIC SMALL LETTER DJERV, CYRILLIC CAPITAL LETTER DJERV +test(0xA64A, 0xA64B, 0x1C88); // CYRILLIC CAPITAL LETTER MONOGRAPH UK, CYRILLIC SMALL LETTER MONOGRAPH UK, CYRILLIC SMALL LETTER UNBLENDED UK +test(0xA64B, 0x1C88, 0xA64A); // CYRILLIC SMALL LETTER MONOGRAPH UK, CYRILLIC SMALL LETTER UNBLENDED UK, CYRILLIC CAPITAL LETTER MONOGRAPH UK +test(0xA64C, 0xA64D); // CYRILLIC CAPITAL LETTER BROAD OMEGA, CYRILLIC SMALL LETTER BROAD OMEGA +test(0xA64D, 0xA64C); // CYRILLIC SMALL LETTER BROAD OMEGA, CYRILLIC CAPITAL LETTER BROAD OMEGA +test(0xA64E, 0xA64F); // CYRILLIC CAPITAL LETTER NEUTRAL YER, CYRILLIC SMALL LETTER NEUTRAL YER +test(0xA64F, 0xA64E); // CYRILLIC SMALL LETTER NEUTRAL YER, CYRILLIC CAPITAL LETTER NEUTRAL YER +test(0xA650, 0xA651); // CYRILLIC CAPITAL LETTER YERU WITH BACK YER, CYRILLIC SMALL LETTER YERU WITH BACK YER +test(0xA651, 0xA650); // CYRILLIC SMALL LETTER YERU WITH BACK YER, CYRILLIC CAPITAL LETTER YERU WITH BACK YER +test(0xA652, 0xA653); // CYRILLIC CAPITAL LETTER IOTIFIED YAT, CYRILLIC SMALL LETTER IOTIFIED YAT +test(0xA653, 0xA652); // CYRILLIC SMALL LETTER IOTIFIED YAT, CYRILLIC CAPITAL LETTER IOTIFIED YAT +test(0xA654, 0xA655); // CYRILLIC CAPITAL LETTER REVERSED YU, CYRILLIC SMALL LETTER REVERSED YU +test(0xA655, 0xA654); // CYRILLIC SMALL LETTER REVERSED YU, CYRILLIC CAPITAL LETTER REVERSED YU +test(0xA656, 0xA657); // CYRILLIC CAPITAL LETTER IOTIFIED A, CYRILLIC SMALL LETTER IOTIFIED A +test(0xA657, 0xA656); // CYRILLIC SMALL LETTER IOTIFIED A, CYRILLIC CAPITAL LETTER IOTIFIED A +test(0xA658, 0xA659); // CYRILLIC CAPITAL LETTER CLOSED LITTLE YUS, CYRILLIC SMALL LETTER CLOSED LITTLE YUS +test(0xA659, 0xA658); // CYRILLIC SMALL LETTER CLOSED LITTLE YUS, CYRILLIC CAPITAL LETTER CLOSED LITTLE YUS +test(0xA65A, 0xA65B); // CYRILLIC CAPITAL LETTER BLENDED YUS, CYRILLIC SMALL LETTER BLENDED YUS +test(0xA65B, 0xA65A); // CYRILLIC SMALL LETTER BLENDED YUS, CYRILLIC CAPITAL LETTER BLENDED YUS +test(0xA65C, 0xA65D); // CYRILLIC CAPITAL LETTER IOTIFIED CLOSED LITTLE YUS, CYRILLIC SMALL LETTER IOTIFIED CLOSED LITTLE YUS +test(0xA65D, 0xA65C); // CYRILLIC SMALL LETTER IOTIFIED CLOSED LITTLE YUS, CYRILLIC CAPITAL LETTER IOTIFIED CLOSED LITTLE YUS +test(0xA65E, 0xA65F); // CYRILLIC CAPITAL LETTER YN, CYRILLIC SMALL LETTER YN +test(0xA65F, 0xA65E); // CYRILLIC SMALL LETTER YN, CYRILLIC CAPITAL LETTER YN +test(0xA660, 0xA661); // CYRILLIC CAPITAL LETTER REVERSED TSE, CYRILLIC SMALL LETTER REVERSED TSE +test(0xA661, 0xA660); // CYRILLIC SMALL LETTER REVERSED TSE, CYRILLIC CAPITAL LETTER REVERSED TSE +test(0xA662, 0xA663); // CYRILLIC CAPITAL LETTER SOFT DE, CYRILLIC SMALL LETTER SOFT DE +test(0xA663, 0xA662); // CYRILLIC SMALL LETTER SOFT DE, CYRILLIC CAPITAL LETTER SOFT DE +test(0xA664, 0xA665); // CYRILLIC CAPITAL LETTER SOFT EL, CYRILLIC SMALL LETTER SOFT EL +test(0xA665, 0xA664); // CYRILLIC SMALL LETTER SOFT EL, CYRILLIC CAPITAL LETTER SOFT EL +test(0xA666, 0xA667); // CYRILLIC CAPITAL LETTER SOFT EM, CYRILLIC SMALL LETTER SOFT EM +test(0xA667, 0xA666); // CYRILLIC SMALL LETTER SOFT EM, CYRILLIC CAPITAL LETTER SOFT EM +test(0xA668, 0xA669); // CYRILLIC CAPITAL LETTER MONOCULAR O, CYRILLIC SMALL LETTER MONOCULAR O +test(0xA669, 0xA668); // CYRILLIC SMALL LETTER MONOCULAR O, CYRILLIC CAPITAL LETTER MONOCULAR O +test(0xA66A, 0xA66B); // CYRILLIC CAPITAL LETTER BINOCULAR O, CYRILLIC SMALL LETTER BINOCULAR O +test(0xA66B, 0xA66A); // CYRILLIC SMALL LETTER BINOCULAR O, CYRILLIC CAPITAL LETTER BINOCULAR O +test(0xA66C, 0xA66D); // CYRILLIC CAPITAL LETTER DOUBLE MONOCULAR O, CYRILLIC SMALL LETTER DOUBLE MONOCULAR O +test(0xA66D, 0xA66C); // CYRILLIC SMALL LETTER DOUBLE MONOCULAR O, CYRILLIC CAPITAL LETTER DOUBLE MONOCULAR O +test(0xA680, 0xA681); // CYRILLIC CAPITAL LETTER DWE, CYRILLIC SMALL LETTER DWE +test(0xA681, 0xA680); // CYRILLIC SMALL LETTER DWE, CYRILLIC CAPITAL LETTER DWE +test(0xA682, 0xA683); // CYRILLIC CAPITAL LETTER DZWE, CYRILLIC SMALL LETTER DZWE +test(0xA683, 0xA682); // CYRILLIC SMALL LETTER DZWE, CYRILLIC CAPITAL LETTER DZWE +test(0xA684, 0xA685); // CYRILLIC CAPITAL LETTER ZHWE, CYRILLIC SMALL LETTER ZHWE +test(0xA685, 0xA684); // CYRILLIC SMALL LETTER ZHWE, CYRILLIC CAPITAL LETTER ZHWE +test(0xA686, 0xA687); // CYRILLIC CAPITAL LETTER CCHE, CYRILLIC SMALL LETTER CCHE +test(0xA687, 0xA686); // CYRILLIC SMALL LETTER CCHE, CYRILLIC CAPITAL LETTER CCHE +test(0xA688, 0xA689); // CYRILLIC CAPITAL LETTER DZZE, CYRILLIC SMALL LETTER DZZE +test(0xA689, 0xA688); // CYRILLIC SMALL LETTER DZZE, CYRILLIC CAPITAL LETTER DZZE +test(0xA68A, 0xA68B); // CYRILLIC CAPITAL LETTER TE WITH MIDDLE HOOK, CYRILLIC SMALL LETTER TE WITH MIDDLE HOOK +test(0xA68B, 0xA68A); // CYRILLIC SMALL LETTER TE WITH MIDDLE HOOK, CYRILLIC CAPITAL LETTER TE WITH MIDDLE HOOK +test(0xA68C, 0xA68D); // CYRILLIC CAPITAL LETTER TWE, CYRILLIC SMALL LETTER TWE +test(0xA68D, 0xA68C); // CYRILLIC SMALL LETTER TWE, CYRILLIC CAPITAL LETTER TWE +test(0xA68E, 0xA68F); // CYRILLIC CAPITAL LETTER TSWE, CYRILLIC SMALL LETTER TSWE +test(0xA68F, 0xA68E); // CYRILLIC SMALL LETTER TSWE, CYRILLIC CAPITAL LETTER TSWE +test(0xA690, 0xA691); // CYRILLIC CAPITAL LETTER TSSE, CYRILLIC SMALL LETTER TSSE +test(0xA691, 0xA690); // CYRILLIC SMALL LETTER TSSE, CYRILLIC CAPITAL LETTER TSSE +test(0xA692, 0xA693); // CYRILLIC CAPITAL LETTER TCHE, CYRILLIC SMALL LETTER TCHE +test(0xA693, 0xA692); // CYRILLIC SMALL LETTER TCHE, CYRILLIC CAPITAL LETTER TCHE +test(0xA694, 0xA695); // CYRILLIC CAPITAL LETTER HWE, CYRILLIC SMALL LETTER HWE +test(0xA695, 0xA694); // CYRILLIC SMALL LETTER HWE, CYRILLIC CAPITAL LETTER HWE +test(0xA696, 0xA697); // CYRILLIC CAPITAL LETTER SHWE, CYRILLIC SMALL LETTER SHWE +test(0xA697, 0xA696); // CYRILLIC SMALL LETTER SHWE, CYRILLIC CAPITAL LETTER SHWE +test(0xA698, 0xA699); // CYRILLIC CAPITAL LETTER DOUBLE O, CYRILLIC SMALL LETTER DOUBLE O +test(0xA699, 0xA698); // CYRILLIC SMALL LETTER DOUBLE O, CYRILLIC CAPITAL LETTER DOUBLE O +test(0xA69A, 0xA69B); // CYRILLIC CAPITAL LETTER CROSSED O, CYRILLIC SMALL LETTER CROSSED O +test(0xA69B, 0xA69A); // CYRILLIC SMALL LETTER CROSSED O, CYRILLIC CAPITAL LETTER CROSSED O +test(0xA722, 0xA723); // LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF, LATIN SMALL LETTER EGYPTOLOGICAL ALEF +test(0xA723, 0xA722); // LATIN SMALL LETTER EGYPTOLOGICAL ALEF, LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF +test(0xA724, 0xA725); // LATIN CAPITAL LETTER EGYPTOLOGICAL AIN, LATIN SMALL LETTER EGYPTOLOGICAL AIN +test(0xA725, 0xA724); // LATIN SMALL LETTER EGYPTOLOGICAL AIN, LATIN CAPITAL LETTER EGYPTOLOGICAL AIN +test(0xA726, 0xA727); // LATIN CAPITAL LETTER HENG, LATIN SMALL LETTER HENG +test(0xA727, 0xA726); // LATIN SMALL LETTER HENG, LATIN CAPITAL LETTER HENG +test(0xA728, 0xA729); // LATIN CAPITAL LETTER TZ, LATIN SMALL LETTER TZ +test(0xA729, 0xA728); // LATIN SMALL LETTER TZ, LATIN CAPITAL LETTER TZ +test(0xA72A, 0xA72B); // LATIN CAPITAL LETTER TRESILLO, LATIN SMALL LETTER TRESILLO +test(0xA72B, 0xA72A); // LATIN SMALL LETTER TRESILLO, LATIN CAPITAL LETTER TRESILLO +test(0xA72C, 0xA72D); // LATIN CAPITAL LETTER CUATRILLO, LATIN SMALL LETTER CUATRILLO +test(0xA72D, 0xA72C); // LATIN SMALL LETTER CUATRILLO, LATIN CAPITAL LETTER CUATRILLO +test(0xA72E, 0xA72F); // LATIN CAPITAL LETTER CUATRILLO WITH COMMA, LATIN SMALL LETTER CUATRILLO WITH COMMA +test(0xA72F, 0xA72E); // LATIN SMALL LETTER CUATRILLO WITH COMMA, LATIN CAPITAL LETTER CUATRILLO WITH COMMA +test(0xA732, 0xA733); // LATIN CAPITAL LETTER AA, LATIN SMALL LETTER AA +test(0xA733, 0xA732); // LATIN SMALL LETTER AA, LATIN CAPITAL LETTER AA +test(0xA734, 0xA735); // LATIN CAPITAL LETTER AO, LATIN SMALL LETTER AO +test(0xA735, 0xA734); // LATIN SMALL LETTER AO, LATIN CAPITAL LETTER AO +test(0xA736, 0xA737); // LATIN CAPITAL LETTER AU, LATIN SMALL LETTER AU +test(0xA737, 0xA736); // LATIN SMALL LETTER AU, LATIN CAPITAL LETTER AU +test(0xA738, 0xA739); // LATIN CAPITAL LETTER AV, LATIN SMALL LETTER AV +test(0xA739, 0xA738); // LATIN SMALL LETTER AV, LATIN CAPITAL LETTER AV +test(0xA73A, 0xA73B); // LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR, LATIN SMALL LETTER AV WITH HORIZONTAL BAR +test(0xA73B, 0xA73A); // LATIN SMALL LETTER AV WITH HORIZONTAL BAR, LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR +test(0xA73C, 0xA73D); // LATIN CAPITAL LETTER AY, LATIN SMALL LETTER AY +test(0xA73D, 0xA73C); // LATIN SMALL LETTER AY, LATIN CAPITAL LETTER AY +test(0xA73E, 0xA73F); // LATIN CAPITAL LETTER REVERSED C WITH DOT, LATIN SMALL LETTER REVERSED C WITH DOT +test(0xA73F, 0xA73E); // LATIN SMALL LETTER REVERSED C WITH DOT, LATIN CAPITAL LETTER REVERSED C WITH DOT +test(0xA740, 0xA741); // LATIN CAPITAL LETTER K WITH STROKE, LATIN SMALL LETTER K WITH STROKE +test(0xA741, 0xA740); // LATIN SMALL LETTER K WITH STROKE, LATIN CAPITAL LETTER K WITH STROKE +test(0xA742, 0xA743); // LATIN CAPITAL LETTER K WITH DIAGONAL STROKE, LATIN SMALL LETTER K WITH DIAGONAL STROKE +test(0xA743, 0xA742); // LATIN SMALL LETTER K WITH DIAGONAL STROKE, LATIN CAPITAL LETTER K WITH DIAGONAL STROKE +test(0xA744, 0xA745); // LATIN CAPITAL LETTER K WITH STROKE AND DIAGONAL STROKE, LATIN SMALL LETTER K WITH STROKE AND DIAGONAL STROKE +test(0xA745, 0xA744); // LATIN SMALL LETTER K WITH STROKE AND DIAGONAL STROKE, LATIN CAPITAL LETTER K WITH STROKE AND DIAGONAL STROKE +test(0xA746, 0xA747); // LATIN CAPITAL LETTER BROKEN L, LATIN SMALL LETTER BROKEN L +test(0xA747, 0xA746); // LATIN SMALL LETTER BROKEN L, LATIN CAPITAL LETTER BROKEN L +test(0xA748, 0xA749); // LATIN CAPITAL LETTER L WITH HIGH STROKE, LATIN SMALL LETTER L WITH HIGH STROKE +test(0xA749, 0xA748); // LATIN SMALL LETTER L WITH HIGH STROKE, LATIN CAPITAL LETTER L WITH HIGH STROKE +test(0xA74A, 0xA74B); // LATIN CAPITAL LETTER O WITH LONG STROKE OVERLAY, LATIN SMALL LETTER O WITH LONG STROKE OVERLAY +test(0xA74B, 0xA74A); // LATIN SMALL LETTER O WITH LONG STROKE OVERLAY, LATIN CAPITAL LETTER O WITH LONG STROKE OVERLAY +test(0xA74C, 0xA74D); // LATIN CAPITAL LETTER O WITH LOOP, LATIN SMALL LETTER O WITH LOOP +test(0xA74D, 0xA74C); // LATIN SMALL LETTER O WITH LOOP, LATIN CAPITAL LETTER O WITH LOOP +test(0xA74E, 0xA74F); // LATIN CAPITAL LETTER OO, LATIN SMALL LETTER OO +test(0xA74F, 0xA74E); // LATIN SMALL LETTER OO, LATIN CAPITAL LETTER OO +test(0xA750, 0xA751); // LATIN CAPITAL LETTER P WITH STROKE THROUGH DESCENDER, LATIN SMALL LETTER P WITH STROKE THROUGH DESCENDER +test(0xA751, 0xA750); // LATIN SMALL LETTER P WITH STROKE THROUGH DESCENDER, LATIN CAPITAL LETTER P WITH STROKE THROUGH DESCENDER +test(0xA752, 0xA753); // LATIN CAPITAL LETTER P WITH FLOURISH, LATIN SMALL LETTER P WITH FLOURISH +test(0xA753, 0xA752); // LATIN SMALL LETTER P WITH FLOURISH, LATIN CAPITAL LETTER P WITH FLOURISH +test(0xA754, 0xA755); // LATIN CAPITAL LETTER P WITH SQUIRREL TAIL, LATIN SMALL LETTER P WITH SQUIRREL TAIL +test(0xA755, 0xA754); // LATIN SMALL LETTER P WITH SQUIRREL TAIL, LATIN CAPITAL LETTER P WITH SQUIRREL TAIL +test(0xA756, 0xA757); // LATIN CAPITAL LETTER Q WITH STROKE THROUGH DESCENDER, LATIN SMALL LETTER Q WITH STROKE THROUGH DESCENDER +test(0xA757, 0xA756); // LATIN SMALL LETTER Q WITH STROKE THROUGH DESCENDER, LATIN CAPITAL LETTER Q WITH STROKE THROUGH DESCENDER +test(0xA758, 0xA759); // LATIN CAPITAL LETTER Q WITH DIAGONAL STROKE, LATIN SMALL LETTER Q WITH DIAGONAL STROKE +test(0xA759, 0xA758); // LATIN SMALL LETTER Q WITH DIAGONAL STROKE, LATIN CAPITAL LETTER Q WITH DIAGONAL STROKE +test(0xA75A, 0xA75B); // LATIN CAPITAL LETTER R ROTUNDA, LATIN SMALL LETTER R ROTUNDA +test(0xA75B, 0xA75A); // LATIN SMALL LETTER R ROTUNDA, LATIN CAPITAL LETTER R ROTUNDA +test(0xA75C, 0xA75D); // LATIN CAPITAL LETTER RUM ROTUNDA, LATIN SMALL LETTER RUM ROTUNDA +test(0xA75D, 0xA75C); // LATIN SMALL LETTER RUM ROTUNDA, LATIN CAPITAL LETTER RUM ROTUNDA +test(0xA75E, 0xA75F); // LATIN CAPITAL LETTER V WITH DIAGONAL STROKE, LATIN SMALL LETTER V WITH DIAGONAL STROKE +test(0xA75F, 0xA75E); // LATIN SMALL LETTER V WITH DIAGONAL STROKE, LATIN CAPITAL LETTER V WITH DIAGONAL STROKE +test(0xA760, 0xA761); // LATIN CAPITAL LETTER VY, LATIN SMALL LETTER VY +test(0xA761, 0xA760); // LATIN SMALL LETTER VY, LATIN CAPITAL LETTER VY +test(0xA762, 0xA763); // LATIN CAPITAL LETTER VISIGOTHIC Z, LATIN SMALL LETTER VISIGOTHIC Z +test(0xA763, 0xA762); // LATIN SMALL LETTER VISIGOTHIC Z, LATIN CAPITAL LETTER VISIGOTHIC Z +test(0xA764, 0xA765); // LATIN CAPITAL LETTER THORN WITH STROKE, LATIN SMALL LETTER THORN WITH STROKE +test(0xA765, 0xA764); // LATIN SMALL LETTER THORN WITH STROKE, LATIN CAPITAL LETTER THORN WITH STROKE +test(0xA766, 0xA767); // LATIN CAPITAL LETTER THORN WITH STROKE THROUGH DESCENDER, LATIN SMALL LETTER THORN WITH STROKE THROUGH DESCENDER +test(0xA767, 0xA766); // LATIN SMALL LETTER THORN WITH STROKE THROUGH DESCENDER, LATIN CAPITAL LETTER THORN WITH STROKE THROUGH DESCENDER +test(0xA768, 0xA769); // LATIN CAPITAL LETTER VEND, LATIN SMALL LETTER VEND +test(0xA769, 0xA768); // LATIN SMALL LETTER VEND, LATIN CAPITAL LETTER VEND +test(0xA76A, 0xA76B); // LATIN CAPITAL LETTER ET, LATIN SMALL LETTER ET +test(0xA76B, 0xA76A); // LATIN SMALL LETTER ET, LATIN CAPITAL LETTER ET +test(0xA76C, 0xA76D); // LATIN CAPITAL LETTER IS, LATIN SMALL LETTER IS +test(0xA76D, 0xA76C); // LATIN SMALL LETTER IS, LATIN CAPITAL LETTER IS +test(0xA76E, 0xA76F); // LATIN CAPITAL LETTER CON, LATIN SMALL LETTER CON +test(0xA76F, 0xA76E); // LATIN SMALL LETTER CON, LATIN CAPITAL LETTER CON +test(0xA779, 0xA77A); // LATIN CAPITAL LETTER INSULAR D, LATIN SMALL LETTER INSULAR D +test(0xA77A, 0xA779); // LATIN SMALL LETTER INSULAR D, LATIN CAPITAL LETTER INSULAR D +test(0xA77B, 0xA77C); // LATIN CAPITAL LETTER INSULAR F, LATIN SMALL LETTER INSULAR F +test(0xA77C, 0xA77B); // LATIN SMALL LETTER INSULAR F, LATIN CAPITAL LETTER INSULAR F +test(0xA77D, 0x1D79); // LATIN CAPITAL LETTER INSULAR G, LATIN SMALL LETTER INSULAR G +test(0xA77E, 0xA77F); // LATIN CAPITAL LETTER TURNED INSULAR G, LATIN SMALL LETTER TURNED INSULAR G +test(0xA77F, 0xA77E); // LATIN SMALL LETTER TURNED INSULAR G, LATIN CAPITAL LETTER TURNED INSULAR G +test(0xA780, 0xA781); // LATIN CAPITAL LETTER TURNED L, LATIN SMALL LETTER TURNED L +test(0xA781, 0xA780); // LATIN SMALL LETTER TURNED L, LATIN CAPITAL LETTER TURNED L +test(0xA782, 0xA783); // LATIN CAPITAL LETTER INSULAR R, LATIN SMALL LETTER INSULAR R +test(0xA783, 0xA782); // LATIN SMALL LETTER INSULAR R, LATIN CAPITAL LETTER INSULAR R +test(0xA784, 0xA785); // LATIN CAPITAL LETTER INSULAR S, LATIN SMALL LETTER INSULAR S +test(0xA785, 0xA784); // LATIN SMALL LETTER INSULAR S, LATIN CAPITAL LETTER INSULAR S +test(0xA786, 0xA787); // LATIN CAPITAL LETTER INSULAR T, LATIN SMALL LETTER INSULAR T +test(0xA787, 0xA786); // LATIN SMALL LETTER INSULAR T, LATIN CAPITAL LETTER INSULAR T +test(0xA78B, 0xA78C); // LATIN CAPITAL LETTER SALTILLO, LATIN SMALL LETTER SALTILLO +test(0xA78C, 0xA78B); // LATIN SMALL LETTER SALTILLO, LATIN CAPITAL LETTER SALTILLO +test(0xA78D, 0x0265); // LATIN CAPITAL LETTER TURNED H, LATIN SMALL LETTER TURNED H +test(0xA790, 0xA791); // LATIN CAPITAL LETTER N WITH DESCENDER, LATIN SMALL LETTER N WITH DESCENDER +test(0xA791, 0xA790); // LATIN SMALL LETTER N WITH DESCENDER, LATIN CAPITAL LETTER N WITH DESCENDER +test(0xA792, 0xA793); // LATIN CAPITAL LETTER C WITH BAR, LATIN SMALL LETTER C WITH BAR +test(0xA793, 0xA792); // LATIN SMALL LETTER C WITH BAR, LATIN CAPITAL LETTER C WITH BAR +test(0xA794, 0xA7C4); // LATIN SMALL LETTER C WITH PALATAL HOOK, LATIN CAPITAL LETTER C WITH PALATAL HOOK +test(0xA796, 0xA797); // LATIN CAPITAL LETTER B WITH FLOURISH, LATIN SMALL LETTER B WITH FLOURISH +test(0xA797, 0xA796); // LATIN SMALL LETTER B WITH FLOURISH, LATIN CAPITAL LETTER B WITH FLOURISH +test(0xA798, 0xA799); // LATIN CAPITAL LETTER F WITH STROKE, LATIN SMALL LETTER F WITH STROKE +test(0xA799, 0xA798); // LATIN SMALL LETTER F WITH STROKE, LATIN CAPITAL LETTER F WITH STROKE +test(0xA79A, 0xA79B); // LATIN CAPITAL LETTER VOLAPUK AE, LATIN SMALL LETTER VOLAPUK AE +test(0xA79B, 0xA79A); // LATIN SMALL LETTER VOLAPUK AE, LATIN CAPITAL LETTER VOLAPUK AE +test(0xA79C, 0xA79D); // LATIN CAPITAL LETTER VOLAPUK OE, LATIN SMALL LETTER VOLAPUK OE +test(0xA79D, 0xA79C); // LATIN SMALL LETTER VOLAPUK OE, LATIN CAPITAL LETTER VOLAPUK OE +test(0xA79E, 0xA79F); // LATIN CAPITAL LETTER VOLAPUK UE, LATIN SMALL LETTER VOLAPUK UE +test(0xA79F, 0xA79E); // LATIN SMALL LETTER VOLAPUK UE, LATIN CAPITAL LETTER VOLAPUK UE +test(0xA7A0, 0xA7A1); // LATIN CAPITAL LETTER G WITH OBLIQUE STROKE, LATIN SMALL LETTER G WITH OBLIQUE STROKE +test(0xA7A1, 0xA7A0); // LATIN SMALL LETTER G WITH OBLIQUE STROKE, LATIN CAPITAL LETTER G WITH OBLIQUE STROKE +test(0xA7A2, 0xA7A3); // LATIN CAPITAL LETTER K WITH OBLIQUE STROKE, LATIN SMALL LETTER K WITH OBLIQUE STROKE +test(0xA7A3, 0xA7A2); // LATIN SMALL LETTER K WITH OBLIQUE STROKE, LATIN CAPITAL LETTER K WITH OBLIQUE STROKE +test(0xA7A4, 0xA7A5); // LATIN CAPITAL LETTER N WITH OBLIQUE STROKE, LATIN SMALL LETTER N WITH OBLIQUE STROKE +test(0xA7A5, 0xA7A4); // LATIN SMALL LETTER N WITH OBLIQUE STROKE, LATIN CAPITAL LETTER N WITH OBLIQUE STROKE +test(0xA7A6, 0xA7A7); // LATIN CAPITAL LETTER R WITH OBLIQUE STROKE, LATIN SMALL LETTER R WITH OBLIQUE STROKE +test(0xA7A7, 0xA7A6); // LATIN SMALL LETTER R WITH OBLIQUE STROKE, LATIN CAPITAL LETTER R WITH OBLIQUE STROKE +test(0xA7A8, 0xA7A9); // LATIN CAPITAL LETTER S WITH OBLIQUE STROKE, LATIN SMALL LETTER S WITH OBLIQUE STROKE +test(0xA7A9, 0xA7A8); // LATIN SMALL LETTER S WITH OBLIQUE STROKE, LATIN CAPITAL LETTER S WITH OBLIQUE STROKE +test(0xA7AA, 0x0266); // LATIN CAPITAL LETTER H WITH HOOK, LATIN SMALL LETTER H WITH HOOK (LATIN SMALL LETTER H HOOK) +test(0xA7AB, 0x025C); // LATIN CAPITAL LETTER REVERSED OPEN E, LATIN SMALL LETTER REVERSED OPEN E (LATIN SMALL LETTER REVERSED EPSILON) +test(0xA7AC, 0x0261); // LATIN CAPITAL LETTER SCRIPT G, LATIN SMALL LETTER SCRIPT G +test(0xA7AD, 0x026C); // LATIN CAPITAL LETTER L WITH BELT, LATIN SMALL LETTER L WITH BELT (LATIN SMALL LETTER L BELT) +test(0xA7AE, 0x026A); // LATIN CAPITAL LETTER SMALL CAPITAL I, LATIN LETTER SMALL CAPITAL I +test(0xA7B0, 0x029E); // LATIN CAPITAL LETTER TURNED K, LATIN SMALL LETTER TURNED K +test(0xA7B1, 0x0287); // LATIN CAPITAL LETTER TURNED T, LATIN SMALL LETTER TURNED T +test(0xA7B2, 0x029D); // LATIN CAPITAL LETTER J WITH CROSSED-TAIL, LATIN SMALL LETTER J WITH CROSSED-TAIL (LATIN SMALL LETTER CROSSED-TAIL J) +test(0xA7B3, 0xAB53); // LATIN CAPITAL LETTER CHI, LATIN SMALL LETTER CHI +test(0xA7B4, 0xA7B5); // LATIN CAPITAL LETTER BETA, LATIN SMALL LETTER BETA +test(0xA7B5, 0xA7B4); // LATIN SMALL LETTER BETA, LATIN CAPITAL LETTER BETA +test(0xA7B6, 0xA7B7); // LATIN CAPITAL LETTER OMEGA, LATIN SMALL LETTER OMEGA +test(0xA7B7, 0xA7B6); // LATIN SMALL LETTER OMEGA, LATIN CAPITAL LETTER OMEGA +test(0xA7B8, 0xA7B9); // LATIN CAPITAL LETTER U WITH STROKE, LATIN SMALL LETTER U WITH STROKE +test(0xA7B9, 0xA7B8); // LATIN SMALL LETTER U WITH STROKE, LATIN CAPITAL LETTER U WITH STROKE +test(0xA7BA, 0xA7BB); // LATIN CAPITAL LETTER GLOTTAL A, LATIN SMALL LETTER GLOTTAL A +test(0xA7BB, 0xA7BA); // LATIN SMALL LETTER GLOTTAL A, LATIN CAPITAL LETTER GLOTTAL A +test(0xA7BC, 0xA7BD); // LATIN CAPITAL LETTER GLOTTAL I, LATIN SMALL LETTER GLOTTAL I +test(0xA7BD, 0xA7BC); // LATIN SMALL LETTER GLOTTAL I, LATIN CAPITAL LETTER GLOTTAL I +test(0xA7BE, 0xA7BF); // LATIN CAPITAL LETTER GLOTTAL U, LATIN SMALL LETTER GLOTTAL U +test(0xA7BF, 0xA7BE); // LATIN SMALL LETTER GLOTTAL U, LATIN CAPITAL LETTER GLOTTAL U +test(0xA7C0, 0xA7C1); // LATIN CAPITAL LETTER OLD POLISH O, LATIN SMALL LETTER OLD POLISH O +test(0xA7C1, 0xA7C0); // LATIN SMALL LETTER OLD POLISH O, LATIN CAPITAL LETTER OLD POLISH O +test(0xA7C2, 0xA7C3); // LATIN CAPITAL LETTER ANGLICANA W, LATIN SMALL LETTER ANGLICANA W +test(0xA7C3, 0xA7C2); // LATIN SMALL LETTER ANGLICANA W, LATIN CAPITAL LETTER ANGLICANA W +test(0xA7C4, 0xA794); // LATIN CAPITAL LETTER C WITH PALATAL HOOK, LATIN SMALL LETTER C WITH PALATAL HOOK +test(0xA7C5, 0x0282); // LATIN CAPITAL LETTER S WITH HOOK, LATIN SMALL LETTER S WITH HOOK (LATIN SMALL LETTER S HOOK) +test(0xA7C6, 0x1D8E); // LATIN CAPITAL LETTER Z WITH PALATAL HOOK, LATIN SMALL LETTER Z WITH PALATAL HOOK +test(0xA7C7, 0xA7C8); // LATIN CAPITAL LETTER D WITH SHORT STROKE OVERLAY, LATIN SMALL LETTER D WITH SHORT STROKE OVERLAY +test(0xA7C8, 0xA7C7); // LATIN SMALL LETTER D WITH SHORT STROKE OVERLAY, LATIN CAPITAL LETTER D WITH SHORT STROKE OVERLAY +test(0xA7C9, 0xA7CA); // LATIN CAPITAL LETTER S WITH SHORT STROKE OVERLAY, LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY +test(0xA7CA, 0xA7C9); // LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY, LATIN CAPITAL LETTER S WITH SHORT STROKE OVERLAY +test(0xA7D0, 0xA7D1); // LATIN CAPITAL LETTER CLOSED INSULAR G, LATIN SMALL LETTER CLOSED INSULAR G +test(0xA7D1, 0xA7D0); // LATIN SMALL LETTER CLOSED INSULAR G, LATIN CAPITAL LETTER CLOSED INSULAR G +test(0xA7D6, 0xA7D7); // LATIN CAPITAL LETTER MIDDLE SCOTS S, LATIN SMALL LETTER MIDDLE SCOTS S +test(0xA7D7, 0xA7D6); // LATIN SMALL LETTER MIDDLE SCOTS S, LATIN CAPITAL LETTER MIDDLE SCOTS S +test(0xA7D8, 0xA7D9); // LATIN CAPITAL LETTER SIGMOID S, LATIN SMALL LETTER SIGMOID S +test(0xA7D9, 0xA7D8); // LATIN SMALL LETTER SIGMOID S, LATIN CAPITAL LETTER SIGMOID S +test(0xA7F5, 0xA7F6); // LATIN CAPITAL LETTER REVERSED HALF H, LATIN SMALL LETTER REVERSED HALF H +test(0xA7F6, 0xA7F5); // LATIN SMALL LETTER REVERSED HALF H, LATIN CAPITAL LETTER REVERSED HALF H +test(0xAB53, 0xA7B3); // LATIN SMALL LETTER CHI, LATIN CAPITAL LETTER CHI +test(0xAB70, 0x13A0); // CHEROKEE SMALL LETTER A, CHEROKEE LETTER A +test(0xAB71, 0x13A1); // CHEROKEE SMALL LETTER E, CHEROKEE LETTER E +test(0xAB72, 0x13A2); // CHEROKEE SMALL LETTER I, CHEROKEE LETTER I +test(0xAB73, 0x13A3); // CHEROKEE SMALL LETTER O, CHEROKEE LETTER O +test(0xAB74, 0x13A4); // CHEROKEE SMALL LETTER U, CHEROKEE LETTER U +test(0xAB75, 0x13A5); // CHEROKEE SMALL LETTER V, CHEROKEE LETTER V +test(0xAB76, 0x13A6); // CHEROKEE SMALL LETTER GA, CHEROKEE LETTER GA +test(0xAB77, 0x13A7); // CHEROKEE SMALL LETTER KA, CHEROKEE LETTER KA +test(0xAB78, 0x13A8); // CHEROKEE SMALL LETTER GE, CHEROKEE LETTER GE +test(0xAB79, 0x13A9); // CHEROKEE SMALL LETTER GI, CHEROKEE LETTER GI +test(0xAB7A, 0x13AA); // CHEROKEE SMALL LETTER GO, CHEROKEE LETTER GO +test(0xAB7B, 0x13AB); // CHEROKEE SMALL LETTER GU, CHEROKEE LETTER GU +test(0xAB7C, 0x13AC); // CHEROKEE SMALL LETTER GV, CHEROKEE LETTER GV +test(0xAB7D, 0x13AD); // CHEROKEE SMALL LETTER HA, CHEROKEE LETTER HA +test(0xAB7E, 0x13AE); // CHEROKEE SMALL LETTER HE, CHEROKEE LETTER HE +test(0xAB7F, 0x13AF); // CHEROKEE SMALL LETTER HI, CHEROKEE LETTER HI +test(0xAB80, 0x13B0); // CHEROKEE SMALL LETTER HO, CHEROKEE LETTER HO +test(0xAB81, 0x13B1); // CHEROKEE SMALL LETTER HU, CHEROKEE LETTER HU +test(0xAB82, 0x13B2); // CHEROKEE SMALL LETTER HV, CHEROKEE LETTER HV +test(0xAB83, 0x13B3); // CHEROKEE SMALL LETTER LA, CHEROKEE LETTER LA +test(0xAB84, 0x13B4); // CHEROKEE SMALL LETTER LE, CHEROKEE LETTER LE +test(0xAB85, 0x13B5); // CHEROKEE SMALL LETTER LI, CHEROKEE LETTER LI +test(0xAB86, 0x13B6); // CHEROKEE SMALL LETTER LO, CHEROKEE LETTER LO +test(0xAB87, 0x13B7); // CHEROKEE SMALL LETTER LU, CHEROKEE LETTER LU +test(0xAB88, 0x13B8); // CHEROKEE SMALL LETTER LV, CHEROKEE LETTER LV +test(0xAB89, 0x13B9); // CHEROKEE SMALL LETTER MA, CHEROKEE LETTER MA +test(0xAB8A, 0x13BA); // CHEROKEE SMALL LETTER ME, CHEROKEE LETTER ME +test(0xAB8B, 0x13BB); // CHEROKEE SMALL LETTER MI, CHEROKEE LETTER MI +test(0xAB8C, 0x13BC); // CHEROKEE SMALL LETTER MO, CHEROKEE LETTER MO +test(0xAB8D, 0x13BD); // CHEROKEE SMALL LETTER MU, CHEROKEE LETTER MU +test(0xAB8E, 0x13BE); // CHEROKEE SMALL LETTER NA, CHEROKEE LETTER NA +test(0xAB8F, 0x13BF); // CHEROKEE SMALL LETTER HNA, CHEROKEE LETTER HNA +test(0xAB90, 0x13C0); // CHEROKEE SMALL LETTER NAH, CHEROKEE LETTER NAH +test(0xAB91, 0x13C1); // CHEROKEE SMALL LETTER NE, CHEROKEE LETTER NE +test(0xAB92, 0x13C2); // CHEROKEE SMALL LETTER NI, CHEROKEE LETTER NI +test(0xAB93, 0x13C3); // CHEROKEE SMALL LETTER NO, CHEROKEE LETTER NO +test(0xAB94, 0x13C4); // CHEROKEE SMALL LETTER NU, CHEROKEE LETTER NU +test(0xAB95, 0x13C5); // CHEROKEE SMALL LETTER NV, CHEROKEE LETTER NV +test(0xAB96, 0x13C6); // CHEROKEE SMALL LETTER QUA, CHEROKEE LETTER QUA +test(0xAB97, 0x13C7); // CHEROKEE SMALL LETTER QUE, CHEROKEE LETTER QUE +test(0xAB98, 0x13C8); // CHEROKEE SMALL LETTER QUI, CHEROKEE LETTER QUI +test(0xAB99, 0x13C9); // CHEROKEE SMALL LETTER QUO, CHEROKEE LETTER QUO +test(0xAB9A, 0x13CA); // CHEROKEE SMALL LETTER QUU, CHEROKEE LETTER QUU +test(0xAB9B, 0x13CB); // CHEROKEE SMALL LETTER QUV, CHEROKEE LETTER QUV +test(0xAB9C, 0x13CC); // CHEROKEE SMALL LETTER SA, CHEROKEE LETTER SA +test(0xAB9D, 0x13CD); // CHEROKEE SMALL LETTER S, CHEROKEE LETTER S +test(0xAB9E, 0x13CE); // CHEROKEE SMALL LETTER SE, CHEROKEE LETTER SE +test(0xAB9F, 0x13CF); // CHEROKEE SMALL LETTER SI, CHEROKEE LETTER SI +test(0xABA0, 0x13D0); // CHEROKEE SMALL LETTER SO, CHEROKEE LETTER SO +test(0xABA1, 0x13D1); // CHEROKEE SMALL LETTER SU, CHEROKEE LETTER SU +test(0xABA2, 0x13D2); // CHEROKEE SMALL LETTER SV, CHEROKEE LETTER SV +test(0xABA3, 0x13D3); // CHEROKEE SMALL LETTER DA, CHEROKEE LETTER DA +test(0xABA4, 0x13D4); // CHEROKEE SMALL LETTER TA, CHEROKEE LETTER TA +test(0xABA5, 0x13D5); // CHEROKEE SMALL LETTER DE, CHEROKEE LETTER DE +test(0xABA6, 0x13D6); // CHEROKEE SMALL LETTER TE, CHEROKEE LETTER TE +test(0xABA7, 0x13D7); // CHEROKEE SMALL LETTER DI, CHEROKEE LETTER DI +test(0xABA8, 0x13D8); // CHEROKEE SMALL LETTER TI, CHEROKEE LETTER TI +test(0xABA9, 0x13D9); // CHEROKEE SMALL LETTER DO, CHEROKEE LETTER DO +test(0xABAA, 0x13DA); // CHEROKEE SMALL LETTER DU, CHEROKEE LETTER DU +test(0xABAB, 0x13DB); // CHEROKEE SMALL LETTER DV, CHEROKEE LETTER DV +test(0xABAC, 0x13DC); // CHEROKEE SMALL LETTER DLA, CHEROKEE LETTER DLA +test(0xABAD, 0x13DD); // CHEROKEE SMALL LETTER TLA, CHEROKEE LETTER TLA +test(0xABAE, 0x13DE); // CHEROKEE SMALL LETTER TLE, CHEROKEE LETTER TLE +test(0xABAF, 0x13DF); // CHEROKEE SMALL LETTER TLI, CHEROKEE LETTER TLI +test(0xABB0, 0x13E0); // CHEROKEE SMALL LETTER TLO, CHEROKEE LETTER TLO +test(0xABB1, 0x13E1); // CHEROKEE SMALL LETTER TLU, CHEROKEE LETTER TLU +test(0xABB2, 0x13E2); // CHEROKEE SMALL LETTER TLV, CHEROKEE LETTER TLV +test(0xABB3, 0x13E3); // CHEROKEE SMALL LETTER TSA, CHEROKEE LETTER TSA +test(0xABB4, 0x13E4); // CHEROKEE SMALL LETTER TSE, CHEROKEE LETTER TSE +test(0xABB5, 0x13E5); // CHEROKEE SMALL LETTER TSI, CHEROKEE LETTER TSI +test(0xABB6, 0x13E6); // CHEROKEE SMALL LETTER TSO, CHEROKEE LETTER TSO +test(0xABB7, 0x13E7); // CHEROKEE SMALL LETTER TSU, CHEROKEE LETTER TSU +test(0xABB8, 0x13E8); // CHEROKEE SMALL LETTER TSV, CHEROKEE LETTER TSV +test(0xABB9, 0x13E9); // CHEROKEE SMALL LETTER WA, CHEROKEE LETTER WA +test(0xABBA, 0x13EA); // CHEROKEE SMALL LETTER WE, CHEROKEE LETTER WE +test(0xABBB, 0x13EB); // CHEROKEE SMALL LETTER WI, CHEROKEE LETTER WI +test(0xABBC, 0x13EC); // CHEROKEE SMALL LETTER WO, CHEROKEE LETTER WO +test(0xABBD, 0x13ED); // CHEROKEE SMALL LETTER WU, CHEROKEE LETTER WU +test(0xABBE, 0x13EE); // CHEROKEE SMALL LETTER WV, CHEROKEE LETTER WV +test(0xABBF, 0x13EF); // CHEROKEE SMALL LETTER YA, CHEROKEE LETTER YA +test(0xFF21, 0xFF41); // FULLWIDTH LATIN CAPITAL LETTER A, FULLWIDTH LATIN SMALL LETTER A +test(0xFF22, 0xFF42); // FULLWIDTH LATIN CAPITAL LETTER B, FULLWIDTH LATIN SMALL LETTER B +test(0xFF23, 0xFF43); // FULLWIDTH LATIN CAPITAL LETTER C, FULLWIDTH LATIN SMALL LETTER C +test(0xFF24, 0xFF44); // FULLWIDTH LATIN CAPITAL LETTER D, FULLWIDTH LATIN SMALL LETTER D +test(0xFF25, 0xFF45); // FULLWIDTH LATIN CAPITAL LETTER E, FULLWIDTH LATIN SMALL LETTER E +test(0xFF26, 0xFF46); // FULLWIDTH LATIN CAPITAL LETTER F, FULLWIDTH LATIN SMALL LETTER F +test(0xFF27, 0xFF47); // FULLWIDTH LATIN CAPITAL LETTER G, FULLWIDTH LATIN SMALL LETTER G +test(0xFF28, 0xFF48); // FULLWIDTH LATIN CAPITAL LETTER H, FULLWIDTH LATIN SMALL LETTER H +test(0xFF29, 0xFF49); // FULLWIDTH LATIN CAPITAL LETTER I, FULLWIDTH LATIN SMALL LETTER I +test(0xFF2A, 0xFF4A); // FULLWIDTH LATIN CAPITAL LETTER J, FULLWIDTH LATIN SMALL LETTER J +test(0xFF2B, 0xFF4B); // FULLWIDTH LATIN CAPITAL LETTER K, FULLWIDTH LATIN SMALL LETTER K +test(0xFF2C, 0xFF4C); // FULLWIDTH LATIN CAPITAL LETTER L, FULLWIDTH LATIN SMALL LETTER L +test(0xFF2D, 0xFF4D); // FULLWIDTH LATIN CAPITAL LETTER M, FULLWIDTH LATIN SMALL LETTER M +test(0xFF2E, 0xFF4E); // FULLWIDTH LATIN CAPITAL LETTER N, FULLWIDTH LATIN SMALL LETTER N +test(0xFF2F, 0xFF4F); // FULLWIDTH LATIN CAPITAL LETTER O, FULLWIDTH LATIN SMALL LETTER O +test(0xFF30, 0xFF50); // FULLWIDTH LATIN CAPITAL LETTER P, FULLWIDTH LATIN SMALL LETTER P +test(0xFF31, 0xFF51); // FULLWIDTH LATIN CAPITAL LETTER Q, FULLWIDTH LATIN SMALL LETTER Q +test(0xFF32, 0xFF52); // FULLWIDTH LATIN CAPITAL LETTER R, FULLWIDTH LATIN SMALL LETTER R +test(0xFF33, 0xFF53); // FULLWIDTH LATIN CAPITAL LETTER S, FULLWIDTH LATIN SMALL LETTER S +test(0xFF34, 0xFF54); // FULLWIDTH LATIN CAPITAL LETTER T, FULLWIDTH LATIN SMALL LETTER T +test(0xFF35, 0xFF55); // FULLWIDTH LATIN CAPITAL LETTER U, FULLWIDTH LATIN SMALL LETTER U +test(0xFF36, 0xFF56); // FULLWIDTH LATIN CAPITAL LETTER V, FULLWIDTH LATIN SMALL LETTER V +test(0xFF37, 0xFF57); // FULLWIDTH LATIN CAPITAL LETTER W, FULLWIDTH LATIN SMALL LETTER W +test(0xFF38, 0xFF58); // FULLWIDTH LATIN CAPITAL LETTER X, FULLWIDTH LATIN SMALL LETTER X +test(0xFF39, 0xFF59); // FULLWIDTH LATIN CAPITAL LETTER Y, FULLWIDTH LATIN SMALL LETTER Y +test(0xFF3A, 0xFF5A); // FULLWIDTH LATIN CAPITAL LETTER Z, FULLWIDTH LATIN SMALL LETTER Z +test(0xFF41, 0xFF21); // FULLWIDTH LATIN SMALL LETTER A, FULLWIDTH LATIN CAPITAL LETTER A +test(0xFF42, 0xFF22); // FULLWIDTH LATIN SMALL LETTER B, FULLWIDTH LATIN CAPITAL LETTER B +test(0xFF43, 0xFF23); // FULLWIDTH LATIN SMALL LETTER C, FULLWIDTH LATIN CAPITAL LETTER C +test(0xFF44, 0xFF24); // FULLWIDTH LATIN SMALL LETTER D, FULLWIDTH LATIN CAPITAL LETTER D +test(0xFF45, 0xFF25); // FULLWIDTH LATIN SMALL LETTER E, FULLWIDTH LATIN CAPITAL LETTER E +test(0xFF46, 0xFF26); // FULLWIDTH LATIN SMALL LETTER F, FULLWIDTH LATIN CAPITAL LETTER F +test(0xFF47, 0xFF27); // FULLWIDTH LATIN SMALL LETTER G, FULLWIDTH LATIN CAPITAL LETTER G +test(0xFF48, 0xFF28); // FULLWIDTH LATIN SMALL LETTER H, FULLWIDTH LATIN CAPITAL LETTER H +test(0xFF49, 0xFF29); // FULLWIDTH LATIN SMALL LETTER I, FULLWIDTH LATIN CAPITAL LETTER I +test(0xFF4A, 0xFF2A); // FULLWIDTH LATIN SMALL LETTER J, FULLWIDTH LATIN CAPITAL LETTER J +test(0xFF4B, 0xFF2B); // FULLWIDTH LATIN SMALL LETTER K, FULLWIDTH LATIN CAPITAL LETTER K +test(0xFF4C, 0xFF2C); // FULLWIDTH LATIN SMALL LETTER L, FULLWIDTH LATIN CAPITAL LETTER L +test(0xFF4D, 0xFF2D); // FULLWIDTH LATIN SMALL LETTER M, FULLWIDTH LATIN CAPITAL LETTER M +test(0xFF4E, 0xFF2E); // FULLWIDTH LATIN SMALL LETTER N, FULLWIDTH LATIN CAPITAL LETTER N +test(0xFF4F, 0xFF2F); // FULLWIDTH LATIN SMALL LETTER O, FULLWIDTH LATIN CAPITAL LETTER O +test(0xFF50, 0xFF30); // FULLWIDTH LATIN SMALL LETTER P, FULLWIDTH LATIN CAPITAL LETTER P +test(0xFF51, 0xFF31); // FULLWIDTH LATIN SMALL LETTER Q, FULLWIDTH LATIN CAPITAL LETTER Q +test(0xFF52, 0xFF32); // FULLWIDTH LATIN SMALL LETTER R, FULLWIDTH LATIN CAPITAL LETTER R +test(0xFF53, 0xFF33); // FULLWIDTH LATIN SMALL LETTER S, FULLWIDTH LATIN CAPITAL LETTER S +test(0xFF54, 0xFF34); // FULLWIDTH LATIN SMALL LETTER T, FULLWIDTH LATIN CAPITAL LETTER T +test(0xFF55, 0xFF35); // FULLWIDTH LATIN SMALL LETTER U, FULLWIDTH LATIN CAPITAL LETTER U +test(0xFF56, 0xFF36); // FULLWIDTH LATIN SMALL LETTER V, FULLWIDTH LATIN CAPITAL LETTER V +test(0xFF57, 0xFF37); // FULLWIDTH LATIN SMALL LETTER W, FULLWIDTH LATIN CAPITAL LETTER W +test(0xFF58, 0xFF38); // FULLWIDTH LATIN SMALL LETTER X, FULLWIDTH LATIN CAPITAL LETTER X +test(0xFF59, 0xFF39); // FULLWIDTH LATIN SMALL LETTER Y, FULLWIDTH LATIN CAPITAL LETTER Y +test(0xFF5A, 0xFF3A); // FULLWIDTH LATIN SMALL LETTER Z, FULLWIDTH LATIN CAPITAL LETTER Z +test(0x10400, 0x10428); // DESERET CAPITAL LETTER LONG I, DESERET SMALL LETTER LONG I +test(0x10401, 0x10429); // DESERET CAPITAL LETTER LONG E, DESERET SMALL LETTER LONG E +test(0x10402, 0x1042A); // DESERET CAPITAL LETTER LONG A, DESERET SMALL LETTER LONG A +test(0x10403, 0x1042B); // DESERET CAPITAL LETTER LONG AH, DESERET SMALL LETTER LONG AH +test(0x10404, 0x1042C); // DESERET CAPITAL LETTER LONG O, DESERET SMALL LETTER LONG O +test(0x10405, 0x1042D); // DESERET CAPITAL LETTER LONG OO, DESERET SMALL LETTER LONG OO +test(0x10406, 0x1042E); // DESERET CAPITAL LETTER SHORT I, DESERET SMALL LETTER SHORT I +test(0x10407, 0x1042F); // DESERET CAPITAL LETTER SHORT E, DESERET SMALL LETTER SHORT E +test(0x10408, 0x10430); // DESERET CAPITAL LETTER SHORT A, DESERET SMALL LETTER SHORT A +test(0x10409, 0x10431); // DESERET CAPITAL LETTER SHORT AH, DESERET SMALL LETTER SHORT AH +test(0x1040A, 0x10432); // DESERET CAPITAL LETTER SHORT O, DESERET SMALL LETTER SHORT O +test(0x1040B, 0x10433); // DESERET CAPITAL LETTER SHORT OO, DESERET SMALL LETTER SHORT OO +test(0x1040C, 0x10434); // DESERET CAPITAL LETTER AY, DESERET SMALL LETTER AY +test(0x1040D, 0x10435); // DESERET CAPITAL LETTER OW, DESERET SMALL LETTER OW +test(0x1040E, 0x10436); // DESERET CAPITAL LETTER WU, DESERET SMALL LETTER WU +test(0x1040F, 0x10437); // DESERET CAPITAL LETTER YEE, DESERET SMALL LETTER YEE +test(0x10410, 0x10438); // DESERET CAPITAL LETTER H, DESERET SMALL LETTER H +test(0x10411, 0x10439); // DESERET CAPITAL LETTER PEE, DESERET SMALL LETTER PEE +test(0x10412, 0x1043A); // DESERET CAPITAL LETTER BEE, DESERET SMALL LETTER BEE +test(0x10413, 0x1043B); // DESERET CAPITAL LETTER TEE, DESERET SMALL LETTER TEE +test(0x10414, 0x1043C); // DESERET CAPITAL LETTER DEE, DESERET SMALL LETTER DEE +test(0x10415, 0x1043D); // DESERET CAPITAL LETTER CHEE, DESERET SMALL LETTER CHEE +test(0x10416, 0x1043E); // DESERET CAPITAL LETTER JEE, DESERET SMALL LETTER JEE +test(0x10417, 0x1043F); // DESERET CAPITAL LETTER KAY, DESERET SMALL LETTER KAY +test(0x10418, 0x10440); // DESERET CAPITAL LETTER GAY, DESERET SMALL LETTER GAY +test(0x10419, 0x10441); // DESERET CAPITAL LETTER EF, DESERET SMALL LETTER EF +test(0x1041A, 0x10442); // DESERET CAPITAL LETTER VEE, DESERET SMALL LETTER VEE +test(0x1041B, 0x10443); // DESERET CAPITAL LETTER ETH, DESERET SMALL LETTER ETH +test(0x1041C, 0x10444); // DESERET CAPITAL LETTER THEE, DESERET SMALL LETTER THEE +test(0x1041D, 0x10445); // DESERET CAPITAL LETTER ES, DESERET SMALL LETTER ES +test(0x1041E, 0x10446); // DESERET CAPITAL LETTER ZEE, DESERET SMALL LETTER ZEE +test(0x1041F, 0x10447); // DESERET CAPITAL LETTER ESH, DESERET SMALL LETTER ESH +test(0x10420, 0x10448); // DESERET CAPITAL LETTER ZHEE, DESERET SMALL LETTER ZHEE +test(0x10421, 0x10449); // DESERET CAPITAL LETTER ER, DESERET SMALL LETTER ER +test(0x10422, 0x1044A); // DESERET CAPITAL LETTER EL, DESERET SMALL LETTER EL +test(0x10423, 0x1044B); // DESERET CAPITAL LETTER EM, DESERET SMALL LETTER EM +test(0x10424, 0x1044C); // DESERET CAPITAL LETTER EN, DESERET SMALL LETTER EN +test(0x10425, 0x1044D); // DESERET CAPITAL LETTER ENG, DESERET SMALL LETTER ENG +test(0x10426, 0x1044E); // DESERET CAPITAL LETTER OI, DESERET SMALL LETTER OI +test(0x10427, 0x1044F); // DESERET CAPITAL LETTER EW, DESERET SMALL LETTER EW +test(0x10428, 0x10400); // DESERET SMALL LETTER LONG I, DESERET CAPITAL LETTER LONG I +test(0x10429, 0x10401); // DESERET SMALL LETTER LONG E, DESERET CAPITAL LETTER LONG E +test(0x1042A, 0x10402); // DESERET SMALL LETTER LONG A, DESERET CAPITAL LETTER LONG A +test(0x1042B, 0x10403); // DESERET SMALL LETTER LONG AH, DESERET CAPITAL LETTER LONG AH +test(0x1042C, 0x10404); // DESERET SMALL LETTER LONG O, DESERET CAPITAL LETTER LONG O +test(0x1042D, 0x10405); // DESERET SMALL LETTER LONG OO, DESERET CAPITAL LETTER LONG OO +test(0x1042E, 0x10406); // DESERET SMALL LETTER SHORT I, DESERET CAPITAL LETTER SHORT I +test(0x1042F, 0x10407); // DESERET SMALL LETTER SHORT E, DESERET CAPITAL LETTER SHORT E +test(0x10430, 0x10408); // DESERET SMALL LETTER SHORT A, DESERET CAPITAL LETTER SHORT A +test(0x10431, 0x10409); // DESERET SMALL LETTER SHORT AH, DESERET CAPITAL LETTER SHORT AH +test(0x10432, 0x1040A); // DESERET SMALL LETTER SHORT O, DESERET CAPITAL LETTER SHORT O +test(0x10433, 0x1040B); // DESERET SMALL LETTER SHORT OO, DESERET CAPITAL LETTER SHORT OO +test(0x10434, 0x1040C); // DESERET SMALL LETTER AY, DESERET CAPITAL LETTER AY +test(0x10435, 0x1040D); // DESERET SMALL LETTER OW, DESERET CAPITAL LETTER OW +test(0x10436, 0x1040E); // DESERET SMALL LETTER WU, DESERET CAPITAL LETTER WU +test(0x10437, 0x1040F); // DESERET SMALL LETTER YEE, DESERET CAPITAL LETTER YEE +test(0x10438, 0x10410); // DESERET SMALL LETTER H, DESERET CAPITAL LETTER H +test(0x10439, 0x10411); // DESERET SMALL LETTER PEE, DESERET CAPITAL LETTER PEE +test(0x1043A, 0x10412); // DESERET SMALL LETTER BEE, DESERET CAPITAL LETTER BEE +test(0x1043B, 0x10413); // DESERET SMALL LETTER TEE, DESERET CAPITAL LETTER TEE +test(0x1043C, 0x10414); // DESERET SMALL LETTER DEE, DESERET CAPITAL LETTER DEE +test(0x1043D, 0x10415); // DESERET SMALL LETTER CHEE, DESERET CAPITAL LETTER CHEE +test(0x1043E, 0x10416); // DESERET SMALL LETTER JEE, DESERET CAPITAL LETTER JEE +test(0x1043F, 0x10417); // DESERET SMALL LETTER KAY, DESERET CAPITAL LETTER KAY +test(0x10440, 0x10418); // DESERET SMALL LETTER GAY, DESERET CAPITAL LETTER GAY +test(0x10441, 0x10419); // DESERET SMALL LETTER EF, DESERET CAPITAL LETTER EF +test(0x10442, 0x1041A); // DESERET SMALL LETTER VEE, DESERET CAPITAL LETTER VEE +test(0x10443, 0x1041B); // DESERET SMALL LETTER ETH, DESERET CAPITAL LETTER ETH +test(0x10444, 0x1041C); // DESERET SMALL LETTER THEE, DESERET CAPITAL LETTER THEE +test(0x10445, 0x1041D); // DESERET SMALL LETTER ES, DESERET CAPITAL LETTER ES +test(0x10446, 0x1041E); // DESERET SMALL LETTER ZEE, DESERET CAPITAL LETTER ZEE +test(0x10447, 0x1041F); // DESERET SMALL LETTER ESH, DESERET CAPITAL LETTER ESH +test(0x10448, 0x10420); // DESERET SMALL LETTER ZHEE, DESERET CAPITAL LETTER ZHEE +test(0x10449, 0x10421); // DESERET SMALL LETTER ER, DESERET CAPITAL LETTER ER +test(0x1044A, 0x10422); // DESERET SMALL LETTER EL, DESERET CAPITAL LETTER EL +test(0x1044B, 0x10423); // DESERET SMALL LETTER EM, DESERET CAPITAL LETTER EM +test(0x1044C, 0x10424); // DESERET SMALL LETTER EN, DESERET CAPITAL LETTER EN +test(0x1044D, 0x10425); // DESERET SMALL LETTER ENG, DESERET CAPITAL LETTER ENG +test(0x1044E, 0x10426); // DESERET SMALL LETTER OI, DESERET CAPITAL LETTER OI +test(0x1044F, 0x10427); // DESERET SMALL LETTER EW, DESERET CAPITAL LETTER EW +test(0x104B0, 0x104D8); // OSAGE CAPITAL LETTER A, OSAGE SMALL LETTER A +test(0x104B1, 0x104D9); // OSAGE CAPITAL LETTER AI, OSAGE SMALL LETTER AI +test(0x104B2, 0x104DA); // OSAGE CAPITAL LETTER AIN, OSAGE SMALL LETTER AIN +test(0x104B3, 0x104DB); // OSAGE CAPITAL LETTER AH, OSAGE SMALL LETTER AH +test(0x104B4, 0x104DC); // OSAGE CAPITAL LETTER BRA, OSAGE SMALL LETTER BRA +test(0x104B5, 0x104DD); // OSAGE CAPITAL LETTER CHA, OSAGE SMALL LETTER CHA +test(0x104B6, 0x104DE); // OSAGE CAPITAL LETTER EHCHA, OSAGE SMALL LETTER EHCHA +test(0x104B7, 0x104DF); // OSAGE CAPITAL LETTER E, OSAGE SMALL LETTER E +test(0x104B8, 0x104E0); // OSAGE CAPITAL LETTER EIN, OSAGE SMALL LETTER EIN +test(0x104B9, 0x104E1); // OSAGE CAPITAL LETTER HA, OSAGE SMALL LETTER HA +test(0x104BA, 0x104E2); // OSAGE CAPITAL LETTER HYA, OSAGE SMALL LETTER HYA +test(0x104BB, 0x104E3); // OSAGE CAPITAL LETTER I, OSAGE SMALL LETTER I +test(0x104BC, 0x104E4); // OSAGE CAPITAL LETTER KA, OSAGE SMALL LETTER KA +test(0x104BD, 0x104E5); // OSAGE CAPITAL LETTER EHKA, OSAGE SMALL LETTER EHKA +test(0x104BE, 0x104E6); // OSAGE CAPITAL LETTER KYA, OSAGE SMALL LETTER KYA +test(0x104BF, 0x104E7); // OSAGE CAPITAL LETTER LA, OSAGE SMALL LETTER LA +test(0x104C0, 0x104E8); // OSAGE CAPITAL LETTER MA, OSAGE SMALL LETTER MA +test(0x104C1, 0x104E9); // OSAGE CAPITAL LETTER NA, OSAGE SMALL LETTER NA +test(0x104C2, 0x104EA); // OSAGE CAPITAL LETTER O, OSAGE SMALL LETTER O +test(0x104C3, 0x104EB); // OSAGE CAPITAL LETTER OIN, OSAGE SMALL LETTER OIN +test(0x104C4, 0x104EC); // OSAGE CAPITAL LETTER PA, OSAGE SMALL LETTER PA +test(0x104C5, 0x104ED); // OSAGE CAPITAL LETTER EHPA, OSAGE SMALL LETTER EHPA +test(0x104C6, 0x104EE); // OSAGE CAPITAL LETTER SA, OSAGE SMALL LETTER SA +test(0x104C7, 0x104EF); // OSAGE CAPITAL LETTER SHA, OSAGE SMALL LETTER SHA +test(0x104C8, 0x104F0); // OSAGE CAPITAL LETTER TA, OSAGE SMALL LETTER TA +test(0x104C9, 0x104F1); // OSAGE CAPITAL LETTER EHTA, OSAGE SMALL LETTER EHTA +test(0x104CA, 0x104F2); // OSAGE CAPITAL LETTER TSA, OSAGE SMALL LETTER TSA +test(0x104CB, 0x104F3); // OSAGE CAPITAL LETTER EHTSA, OSAGE SMALL LETTER EHTSA +test(0x104CC, 0x104F4); // OSAGE CAPITAL LETTER TSHA, OSAGE SMALL LETTER TSHA +test(0x104CD, 0x104F5); // OSAGE CAPITAL LETTER DHA, OSAGE SMALL LETTER DHA +test(0x104CE, 0x104F6); // OSAGE CAPITAL LETTER U, OSAGE SMALL LETTER U +test(0x104CF, 0x104F7); // OSAGE CAPITAL LETTER WA, OSAGE SMALL LETTER WA +test(0x104D0, 0x104F8); // OSAGE CAPITAL LETTER KHA, OSAGE SMALL LETTER KHA +test(0x104D1, 0x104F9); // OSAGE CAPITAL LETTER GHA, OSAGE SMALL LETTER GHA +test(0x104D2, 0x104FA); // OSAGE CAPITAL LETTER ZA, OSAGE SMALL LETTER ZA +test(0x104D3, 0x104FB); // OSAGE CAPITAL LETTER ZHA, OSAGE SMALL LETTER ZHA +test(0x104D8, 0x104B0); // OSAGE SMALL LETTER A, OSAGE CAPITAL LETTER A +test(0x104D9, 0x104B1); // OSAGE SMALL LETTER AI, OSAGE CAPITAL LETTER AI +test(0x104DA, 0x104B2); // OSAGE SMALL LETTER AIN, OSAGE CAPITAL LETTER AIN +test(0x104DB, 0x104B3); // OSAGE SMALL LETTER AH, OSAGE CAPITAL LETTER AH +test(0x104DC, 0x104B4); // OSAGE SMALL LETTER BRA, OSAGE CAPITAL LETTER BRA +test(0x104DD, 0x104B5); // OSAGE SMALL LETTER CHA, OSAGE CAPITAL LETTER CHA +test(0x104DE, 0x104B6); // OSAGE SMALL LETTER EHCHA, OSAGE CAPITAL LETTER EHCHA +test(0x104DF, 0x104B7); // OSAGE SMALL LETTER E, OSAGE CAPITAL LETTER E +test(0x104E0, 0x104B8); // OSAGE SMALL LETTER EIN, OSAGE CAPITAL LETTER EIN +test(0x104E1, 0x104B9); // OSAGE SMALL LETTER HA, OSAGE CAPITAL LETTER HA +test(0x104E2, 0x104BA); // OSAGE SMALL LETTER HYA, OSAGE CAPITAL LETTER HYA +test(0x104E3, 0x104BB); // OSAGE SMALL LETTER I, OSAGE CAPITAL LETTER I +test(0x104E4, 0x104BC); // OSAGE SMALL LETTER KA, OSAGE CAPITAL LETTER KA +test(0x104E5, 0x104BD); // OSAGE SMALL LETTER EHKA, OSAGE CAPITAL LETTER EHKA +test(0x104E6, 0x104BE); // OSAGE SMALL LETTER KYA, OSAGE CAPITAL LETTER KYA +test(0x104E7, 0x104BF); // OSAGE SMALL LETTER LA, OSAGE CAPITAL LETTER LA +test(0x104E8, 0x104C0); // OSAGE SMALL LETTER MA, OSAGE CAPITAL LETTER MA +test(0x104E9, 0x104C1); // OSAGE SMALL LETTER NA, OSAGE CAPITAL LETTER NA +test(0x104EA, 0x104C2); // OSAGE SMALL LETTER O, OSAGE CAPITAL LETTER O +test(0x104EB, 0x104C3); // OSAGE SMALL LETTER OIN, OSAGE CAPITAL LETTER OIN +test(0x104EC, 0x104C4); // OSAGE SMALL LETTER PA, OSAGE CAPITAL LETTER PA +test(0x104ED, 0x104C5); // OSAGE SMALL LETTER EHPA, OSAGE CAPITAL LETTER EHPA +test(0x104EE, 0x104C6); // OSAGE SMALL LETTER SA, OSAGE CAPITAL LETTER SA +test(0x104EF, 0x104C7); // OSAGE SMALL LETTER SHA, OSAGE CAPITAL LETTER SHA +test(0x104F0, 0x104C8); // OSAGE SMALL LETTER TA, OSAGE CAPITAL LETTER TA +test(0x104F1, 0x104C9); // OSAGE SMALL LETTER EHTA, OSAGE CAPITAL LETTER EHTA +test(0x104F2, 0x104CA); // OSAGE SMALL LETTER TSA, OSAGE CAPITAL LETTER TSA +test(0x104F3, 0x104CB); // OSAGE SMALL LETTER EHTSA, OSAGE CAPITAL LETTER EHTSA +test(0x104F4, 0x104CC); // OSAGE SMALL LETTER TSHA, OSAGE CAPITAL LETTER TSHA +test(0x104F5, 0x104CD); // OSAGE SMALL LETTER DHA, OSAGE CAPITAL LETTER DHA +test(0x104F6, 0x104CE); // OSAGE SMALL LETTER U, OSAGE CAPITAL LETTER U +test(0x104F7, 0x104CF); // OSAGE SMALL LETTER WA, OSAGE CAPITAL LETTER WA +test(0x104F8, 0x104D0); // OSAGE SMALL LETTER KHA, OSAGE CAPITAL LETTER KHA +test(0x104F9, 0x104D1); // OSAGE SMALL LETTER GHA, OSAGE CAPITAL LETTER GHA +test(0x104FA, 0x104D2); // OSAGE SMALL LETTER ZA, OSAGE CAPITAL LETTER ZA +test(0x104FB, 0x104D3); // OSAGE SMALL LETTER ZHA, OSAGE CAPITAL LETTER ZHA +test(0x10570, 0x10597); // VITHKUQI CAPITAL LETTER A, VITHKUQI SMALL LETTER A +test(0x10571, 0x10598); // VITHKUQI CAPITAL LETTER BBE, VITHKUQI SMALL LETTER BBE +test(0x10572, 0x10599); // VITHKUQI CAPITAL LETTER BE, VITHKUQI SMALL LETTER BE +test(0x10573, 0x1059A); // VITHKUQI CAPITAL LETTER CE, VITHKUQI SMALL LETTER CE +test(0x10574, 0x1059B); // VITHKUQI CAPITAL LETTER CHE, VITHKUQI SMALL LETTER CHE +test(0x10575, 0x1059C); // VITHKUQI CAPITAL LETTER DE, VITHKUQI SMALL LETTER DE +test(0x10576, 0x1059D); // VITHKUQI CAPITAL LETTER DHE, VITHKUQI SMALL LETTER DHE +test(0x10577, 0x1059E); // VITHKUQI CAPITAL LETTER EI, VITHKUQI SMALL LETTER EI +test(0x10578, 0x1059F); // VITHKUQI CAPITAL LETTER E, VITHKUQI SMALL LETTER E +test(0x10579, 0x105A0); // VITHKUQI CAPITAL LETTER FE, VITHKUQI SMALL LETTER FE +test(0x1057A, 0x105A1); // VITHKUQI CAPITAL LETTER GA, VITHKUQI SMALL LETTER GA +test(0x1057C, 0x105A3); // VITHKUQI CAPITAL LETTER HA, VITHKUQI SMALL LETTER HA +test(0x1057D, 0x105A4); // VITHKUQI CAPITAL LETTER HHA, VITHKUQI SMALL LETTER HHA +test(0x1057E, 0x105A5); // VITHKUQI CAPITAL LETTER I, VITHKUQI SMALL LETTER I +test(0x1057F, 0x105A6); // VITHKUQI CAPITAL LETTER IJE, VITHKUQI SMALL LETTER IJE +test(0x10580, 0x105A7); // VITHKUQI CAPITAL LETTER JE, VITHKUQI SMALL LETTER JE +test(0x10581, 0x105A8); // VITHKUQI CAPITAL LETTER KA, VITHKUQI SMALL LETTER KA +test(0x10582, 0x105A9); // VITHKUQI CAPITAL LETTER LA, VITHKUQI SMALL LETTER LA +test(0x10583, 0x105AA); // VITHKUQI CAPITAL LETTER LLA, VITHKUQI SMALL LETTER LLA +test(0x10584, 0x105AB); // VITHKUQI CAPITAL LETTER ME, VITHKUQI SMALL LETTER ME +test(0x10585, 0x105AC); // VITHKUQI CAPITAL LETTER NE, VITHKUQI SMALL LETTER NE +test(0x10586, 0x105AD); // VITHKUQI CAPITAL LETTER NJE, VITHKUQI SMALL LETTER NJE +test(0x10587, 0x105AE); // VITHKUQI CAPITAL LETTER O, VITHKUQI SMALL LETTER O +test(0x10588, 0x105AF); // VITHKUQI CAPITAL LETTER PE, VITHKUQI SMALL LETTER PE +test(0x10589, 0x105B0); // VITHKUQI CAPITAL LETTER QA, VITHKUQI SMALL LETTER QA +test(0x1058A, 0x105B1); // VITHKUQI CAPITAL LETTER RE, VITHKUQI SMALL LETTER RE +test(0x1058C, 0x105B3); // VITHKUQI CAPITAL LETTER SE, VITHKUQI SMALL LETTER SE +test(0x1058D, 0x105B4); // VITHKUQI CAPITAL LETTER SHE, VITHKUQI SMALL LETTER SHE +test(0x1058E, 0x105B5); // VITHKUQI CAPITAL LETTER TE, VITHKUQI SMALL LETTER TE +test(0x1058F, 0x105B6); // VITHKUQI CAPITAL LETTER THE, VITHKUQI SMALL LETTER THE +test(0x10590, 0x105B7); // VITHKUQI CAPITAL LETTER U, VITHKUQI SMALL LETTER U +test(0x10591, 0x105B8); // VITHKUQI CAPITAL LETTER VE, VITHKUQI SMALL LETTER VE +test(0x10592, 0x105B9); // VITHKUQI CAPITAL LETTER XE, VITHKUQI SMALL LETTER XE +test(0x10594, 0x105BB); // VITHKUQI CAPITAL LETTER Y, VITHKUQI SMALL LETTER Y +test(0x10595, 0x105BC); // VITHKUQI CAPITAL LETTER ZE, VITHKUQI SMALL LETTER ZE +test(0x10597, 0x10570); // VITHKUQI SMALL LETTER A, VITHKUQI CAPITAL LETTER A +test(0x10598, 0x10571); // VITHKUQI SMALL LETTER BBE, VITHKUQI CAPITAL LETTER BBE +test(0x10599, 0x10572); // VITHKUQI SMALL LETTER BE, VITHKUQI CAPITAL LETTER BE +test(0x1059A, 0x10573); // VITHKUQI SMALL LETTER CE, VITHKUQI CAPITAL LETTER CE +test(0x1059B, 0x10574); // VITHKUQI SMALL LETTER CHE, VITHKUQI CAPITAL LETTER CHE +test(0x1059C, 0x10575); // VITHKUQI SMALL LETTER DE, VITHKUQI CAPITAL LETTER DE +test(0x1059D, 0x10576); // VITHKUQI SMALL LETTER DHE, VITHKUQI CAPITAL LETTER DHE +test(0x1059E, 0x10577); // VITHKUQI SMALL LETTER EI, VITHKUQI CAPITAL LETTER EI +test(0x1059F, 0x10578); // VITHKUQI SMALL LETTER E, VITHKUQI CAPITAL LETTER E +test(0x105A0, 0x10579); // VITHKUQI SMALL LETTER FE, VITHKUQI CAPITAL LETTER FE +test(0x105A1, 0x1057A); // VITHKUQI SMALL LETTER GA, VITHKUQI CAPITAL LETTER GA +test(0x105A3, 0x1057C); // VITHKUQI SMALL LETTER HA, VITHKUQI CAPITAL LETTER HA +test(0x105A4, 0x1057D); // VITHKUQI SMALL LETTER HHA, VITHKUQI CAPITAL LETTER HHA +test(0x105A5, 0x1057E); // VITHKUQI SMALL LETTER I, VITHKUQI CAPITAL LETTER I +test(0x105A6, 0x1057F); // VITHKUQI SMALL LETTER IJE, VITHKUQI CAPITAL LETTER IJE +test(0x105A7, 0x10580); // VITHKUQI SMALL LETTER JE, VITHKUQI CAPITAL LETTER JE +test(0x105A8, 0x10581); // VITHKUQI SMALL LETTER KA, VITHKUQI CAPITAL LETTER KA +test(0x105A9, 0x10582); // VITHKUQI SMALL LETTER LA, VITHKUQI CAPITAL LETTER LA +test(0x105AA, 0x10583); // VITHKUQI SMALL LETTER LLA, VITHKUQI CAPITAL LETTER LLA +test(0x105AB, 0x10584); // VITHKUQI SMALL LETTER ME, VITHKUQI CAPITAL LETTER ME +test(0x105AC, 0x10585); // VITHKUQI SMALL LETTER NE, VITHKUQI CAPITAL LETTER NE +test(0x105AD, 0x10586); // VITHKUQI SMALL LETTER NJE, VITHKUQI CAPITAL LETTER NJE +test(0x105AE, 0x10587); // VITHKUQI SMALL LETTER O, VITHKUQI CAPITAL LETTER O +test(0x105AF, 0x10588); // VITHKUQI SMALL LETTER PE, VITHKUQI CAPITAL LETTER PE +test(0x105B0, 0x10589); // VITHKUQI SMALL LETTER QA, VITHKUQI CAPITAL LETTER QA +test(0x105B1, 0x1058A); // VITHKUQI SMALL LETTER RE, VITHKUQI CAPITAL LETTER RE +test(0x105B3, 0x1058C); // VITHKUQI SMALL LETTER SE, VITHKUQI CAPITAL LETTER SE +test(0x105B4, 0x1058D); // VITHKUQI SMALL LETTER SHE, VITHKUQI CAPITAL LETTER SHE +test(0x105B5, 0x1058E); // VITHKUQI SMALL LETTER TE, VITHKUQI CAPITAL LETTER TE +test(0x105B6, 0x1058F); // VITHKUQI SMALL LETTER THE, VITHKUQI CAPITAL LETTER THE +test(0x105B7, 0x10590); // VITHKUQI SMALL LETTER U, VITHKUQI CAPITAL LETTER U +test(0x105B8, 0x10591); // VITHKUQI SMALL LETTER VE, VITHKUQI CAPITAL LETTER VE +test(0x105B9, 0x10592); // VITHKUQI SMALL LETTER XE, VITHKUQI CAPITAL LETTER XE +test(0x105BB, 0x10594); // VITHKUQI SMALL LETTER Y, VITHKUQI CAPITAL LETTER Y +test(0x105BC, 0x10595); // VITHKUQI SMALL LETTER ZE, VITHKUQI CAPITAL LETTER ZE +test(0x10C80, 0x10CC0); // OLD HUNGARIAN CAPITAL LETTER A, OLD HUNGARIAN SMALL LETTER A +test(0x10C81, 0x10CC1); // OLD HUNGARIAN CAPITAL LETTER AA, OLD HUNGARIAN SMALL LETTER AA +test(0x10C82, 0x10CC2); // OLD HUNGARIAN CAPITAL LETTER EB, OLD HUNGARIAN SMALL LETTER EB +test(0x10C83, 0x10CC3); // OLD HUNGARIAN CAPITAL LETTER AMB, OLD HUNGARIAN SMALL LETTER AMB +test(0x10C84, 0x10CC4); // OLD HUNGARIAN CAPITAL LETTER EC, OLD HUNGARIAN SMALL LETTER EC +test(0x10C85, 0x10CC5); // OLD HUNGARIAN CAPITAL LETTER ENC, OLD HUNGARIAN SMALL LETTER ENC +test(0x10C86, 0x10CC6); // OLD HUNGARIAN CAPITAL LETTER ECS, OLD HUNGARIAN SMALL LETTER ECS +test(0x10C87, 0x10CC7); // OLD HUNGARIAN CAPITAL LETTER ED, OLD HUNGARIAN SMALL LETTER ED +test(0x10C88, 0x10CC8); // OLD HUNGARIAN CAPITAL LETTER AND, OLD HUNGARIAN SMALL LETTER AND +test(0x10C89, 0x10CC9); // OLD HUNGARIAN CAPITAL LETTER E, OLD HUNGARIAN SMALL LETTER E +test(0x10C8A, 0x10CCA); // OLD HUNGARIAN CAPITAL LETTER CLOSE E, OLD HUNGARIAN SMALL LETTER CLOSE E +test(0x10C8B, 0x10CCB); // OLD HUNGARIAN CAPITAL LETTER EE, OLD HUNGARIAN SMALL LETTER EE +test(0x10C8C, 0x10CCC); // OLD HUNGARIAN CAPITAL LETTER EF, OLD HUNGARIAN SMALL LETTER EF +test(0x10C8D, 0x10CCD); // OLD HUNGARIAN CAPITAL LETTER EG, OLD HUNGARIAN SMALL LETTER EG +test(0x10C8E, 0x10CCE); // OLD HUNGARIAN CAPITAL LETTER EGY, OLD HUNGARIAN SMALL LETTER EGY +test(0x10C8F, 0x10CCF); // OLD HUNGARIAN CAPITAL LETTER EH, OLD HUNGARIAN SMALL LETTER EH +test(0x10C90, 0x10CD0); // OLD HUNGARIAN CAPITAL LETTER I, OLD HUNGARIAN SMALL LETTER I +test(0x10C91, 0x10CD1); // OLD HUNGARIAN CAPITAL LETTER II, OLD HUNGARIAN SMALL LETTER II +test(0x10C92, 0x10CD2); // OLD HUNGARIAN CAPITAL LETTER EJ, OLD HUNGARIAN SMALL LETTER EJ +test(0x10C93, 0x10CD3); // OLD HUNGARIAN CAPITAL LETTER EK, OLD HUNGARIAN SMALL LETTER EK +test(0x10C94, 0x10CD4); // OLD HUNGARIAN CAPITAL LETTER AK, OLD HUNGARIAN SMALL LETTER AK +test(0x10C95, 0x10CD5); // OLD HUNGARIAN CAPITAL LETTER UNK, OLD HUNGARIAN SMALL LETTER UNK +test(0x10C96, 0x10CD6); // OLD HUNGARIAN CAPITAL LETTER EL, OLD HUNGARIAN SMALL LETTER EL +test(0x10C97, 0x10CD7); // OLD HUNGARIAN CAPITAL LETTER ELY, OLD HUNGARIAN SMALL LETTER ELY +test(0x10C98, 0x10CD8); // OLD HUNGARIAN CAPITAL LETTER EM, OLD HUNGARIAN SMALL LETTER EM +test(0x10C99, 0x10CD9); // OLD HUNGARIAN CAPITAL LETTER EN, OLD HUNGARIAN SMALL LETTER EN +test(0x10C9A, 0x10CDA); // OLD HUNGARIAN CAPITAL LETTER ENY, OLD HUNGARIAN SMALL LETTER ENY +test(0x10C9B, 0x10CDB); // OLD HUNGARIAN CAPITAL LETTER O, OLD HUNGARIAN SMALL LETTER O +test(0x10C9C, 0x10CDC); // OLD HUNGARIAN CAPITAL LETTER OO, OLD HUNGARIAN SMALL LETTER OO +test(0x10C9D, 0x10CDD); // OLD HUNGARIAN CAPITAL LETTER NIKOLSBURG OE, OLD HUNGARIAN SMALL LETTER NIKOLSBURG OE +test(0x10C9E, 0x10CDE); // OLD HUNGARIAN CAPITAL LETTER RUDIMENTA OE, OLD HUNGARIAN SMALL LETTER RUDIMENTA OE +test(0x10C9F, 0x10CDF); // OLD HUNGARIAN CAPITAL LETTER OEE, OLD HUNGARIAN SMALL LETTER OEE +test(0x10CA0, 0x10CE0); // OLD HUNGARIAN CAPITAL LETTER EP, OLD HUNGARIAN SMALL LETTER EP +test(0x10CA1, 0x10CE1); // OLD HUNGARIAN CAPITAL LETTER EMP, OLD HUNGARIAN SMALL LETTER EMP +test(0x10CA2, 0x10CE2); // OLD HUNGARIAN CAPITAL LETTER ER, OLD HUNGARIAN SMALL LETTER ER +test(0x10CA3, 0x10CE3); // OLD HUNGARIAN CAPITAL LETTER SHORT ER, OLD HUNGARIAN SMALL LETTER SHORT ER +test(0x10CA4, 0x10CE4); // OLD HUNGARIAN CAPITAL LETTER ES, OLD HUNGARIAN SMALL LETTER ES +test(0x10CA5, 0x10CE5); // OLD HUNGARIAN CAPITAL LETTER ESZ, OLD HUNGARIAN SMALL LETTER ESZ +test(0x10CA6, 0x10CE6); // OLD HUNGARIAN CAPITAL LETTER ET, OLD HUNGARIAN SMALL LETTER ET +test(0x10CA7, 0x10CE7); // OLD HUNGARIAN CAPITAL LETTER ENT, OLD HUNGARIAN SMALL LETTER ENT +test(0x10CA8, 0x10CE8); // OLD HUNGARIAN CAPITAL LETTER ETY, OLD HUNGARIAN SMALL LETTER ETY +test(0x10CA9, 0x10CE9); // OLD HUNGARIAN CAPITAL LETTER ECH, OLD HUNGARIAN SMALL LETTER ECH +test(0x10CAA, 0x10CEA); // OLD HUNGARIAN CAPITAL LETTER U, OLD HUNGARIAN SMALL LETTER U +test(0x10CAB, 0x10CEB); // OLD HUNGARIAN CAPITAL LETTER UU, OLD HUNGARIAN SMALL LETTER UU +test(0x10CAC, 0x10CEC); // OLD HUNGARIAN CAPITAL LETTER NIKOLSBURG UE, OLD HUNGARIAN SMALL LETTER NIKOLSBURG UE +test(0x10CAD, 0x10CED); // OLD HUNGARIAN CAPITAL LETTER RUDIMENTA UE, OLD HUNGARIAN SMALL LETTER RUDIMENTA UE +test(0x10CAE, 0x10CEE); // OLD HUNGARIAN CAPITAL LETTER EV, OLD HUNGARIAN SMALL LETTER EV +test(0x10CAF, 0x10CEF); // OLD HUNGARIAN CAPITAL LETTER EZ, OLD HUNGARIAN SMALL LETTER EZ +test(0x10CB0, 0x10CF0); // OLD HUNGARIAN CAPITAL LETTER EZS, OLD HUNGARIAN SMALL LETTER EZS +test(0x10CB1, 0x10CF1); // OLD HUNGARIAN CAPITAL LETTER ENT-SHAPED SIGN, OLD HUNGARIAN SMALL LETTER ENT-SHAPED SIGN +test(0x10CB2, 0x10CF2); // OLD HUNGARIAN CAPITAL LETTER US, OLD HUNGARIAN SMALL LETTER US +test(0x10CC0, 0x10C80); // OLD HUNGARIAN SMALL LETTER A, OLD HUNGARIAN CAPITAL LETTER A +test(0x10CC1, 0x10C81); // OLD HUNGARIAN SMALL LETTER AA, OLD HUNGARIAN CAPITAL LETTER AA +test(0x10CC2, 0x10C82); // OLD HUNGARIAN SMALL LETTER EB, OLD HUNGARIAN CAPITAL LETTER EB +test(0x10CC3, 0x10C83); // OLD HUNGARIAN SMALL LETTER AMB, OLD HUNGARIAN CAPITAL LETTER AMB +test(0x10CC4, 0x10C84); // OLD HUNGARIAN SMALL LETTER EC, OLD HUNGARIAN CAPITAL LETTER EC +test(0x10CC5, 0x10C85); // OLD HUNGARIAN SMALL LETTER ENC, OLD HUNGARIAN CAPITAL LETTER ENC +test(0x10CC6, 0x10C86); // OLD HUNGARIAN SMALL LETTER ECS, OLD HUNGARIAN CAPITAL LETTER ECS +test(0x10CC7, 0x10C87); // OLD HUNGARIAN SMALL LETTER ED, OLD HUNGARIAN CAPITAL LETTER ED +test(0x10CC8, 0x10C88); // OLD HUNGARIAN SMALL LETTER AND, OLD HUNGARIAN CAPITAL LETTER AND +test(0x10CC9, 0x10C89); // OLD HUNGARIAN SMALL LETTER E, OLD HUNGARIAN CAPITAL LETTER E +test(0x10CCA, 0x10C8A); // OLD HUNGARIAN SMALL LETTER CLOSE E, OLD HUNGARIAN CAPITAL LETTER CLOSE E +test(0x10CCB, 0x10C8B); // OLD HUNGARIAN SMALL LETTER EE, OLD HUNGARIAN CAPITAL LETTER EE +test(0x10CCC, 0x10C8C); // OLD HUNGARIAN SMALL LETTER EF, OLD HUNGARIAN CAPITAL LETTER EF +test(0x10CCD, 0x10C8D); // OLD HUNGARIAN SMALL LETTER EG, OLD HUNGARIAN CAPITAL LETTER EG +test(0x10CCE, 0x10C8E); // OLD HUNGARIAN SMALL LETTER EGY, OLD HUNGARIAN CAPITAL LETTER EGY +test(0x10CCF, 0x10C8F); // OLD HUNGARIAN SMALL LETTER EH, OLD HUNGARIAN CAPITAL LETTER EH +test(0x10CD0, 0x10C90); // OLD HUNGARIAN SMALL LETTER I, OLD HUNGARIAN CAPITAL LETTER I +test(0x10CD1, 0x10C91); // OLD HUNGARIAN SMALL LETTER II, OLD HUNGARIAN CAPITAL LETTER II +test(0x10CD2, 0x10C92); // OLD HUNGARIAN SMALL LETTER EJ, OLD HUNGARIAN CAPITAL LETTER EJ +test(0x10CD3, 0x10C93); // OLD HUNGARIAN SMALL LETTER EK, OLD HUNGARIAN CAPITAL LETTER EK +test(0x10CD4, 0x10C94); // OLD HUNGARIAN SMALL LETTER AK, OLD HUNGARIAN CAPITAL LETTER AK +test(0x10CD5, 0x10C95); // OLD HUNGARIAN SMALL LETTER UNK, OLD HUNGARIAN CAPITAL LETTER UNK +test(0x10CD6, 0x10C96); // OLD HUNGARIAN SMALL LETTER EL, OLD HUNGARIAN CAPITAL LETTER EL +test(0x10CD7, 0x10C97); // OLD HUNGARIAN SMALL LETTER ELY, OLD HUNGARIAN CAPITAL LETTER ELY +test(0x10CD8, 0x10C98); // OLD HUNGARIAN SMALL LETTER EM, OLD HUNGARIAN CAPITAL LETTER EM +test(0x10CD9, 0x10C99); // OLD HUNGARIAN SMALL LETTER EN, OLD HUNGARIAN CAPITAL LETTER EN +test(0x10CDA, 0x10C9A); // OLD HUNGARIAN SMALL LETTER ENY, OLD HUNGARIAN CAPITAL LETTER ENY +test(0x10CDB, 0x10C9B); // OLD HUNGARIAN SMALL LETTER O, OLD HUNGARIAN CAPITAL LETTER O +test(0x10CDC, 0x10C9C); // OLD HUNGARIAN SMALL LETTER OO, OLD HUNGARIAN CAPITAL LETTER OO +test(0x10CDD, 0x10C9D); // OLD HUNGARIAN SMALL LETTER NIKOLSBURG OE, OLD HUNGARIAN CAPITAL LETTER NIKOLSBURG OE +test(0x10CDE, 0x10C9E); // OLD HUNGARIAN SMALL LETTER RUDIMENTA OE, OLD HUNGARIAN CAPITAL LETTER RUDIMENTA OE +test(0x10CDF, 0x10C9F); // OLD HUNGARIAN SMALL LETTER OEE, OLD HUNGARIAN CAPITAL LETTER OEE +test(0x10CE0, 0x10CA0); // OLD HUNGARIAN SMALL LETTER EP, OLD HUNGARIAN CAPITAL LETTER EP +test(0x10CE1, 0x10CA1); // OLD HUNGARIAN SMALL LETTER EMP, OLD HUNGARIAN CAPITAL LETTER EMP +test(0x10CE2, 0x10CA2); // OLD HUNGARIAN SMALL LETTER ER, OLD HUNGARIAN CAPITAL LETTER ER +test(0x10CE3, 0x10CA3); // OLD HUNGARIAN SMALL LETTER SHORT ER, OLD HUNGARIAN CAPITAL LETTER SHORT ER +test(0x10CE4, 0x10CA4); // OLD HUNGARIAN SMALL LETTER ES, OLD HUNGARIAN CAPITAL LETTER ES +test(0x10CE5, 0x10CA5); // OLD HUNGARIAN SMALL LETTER ESZ, OLD HUNGARIAN CAPITAL LETTER ESZ +test(0x10CE6, 0x10CA6); // OLD HUNGARIAN SMALL LETTER ET, OLD HUNGARIAN CAPITAL LETTER ET +test(0x10CE7, 0x10CA7); // OLD HUNGARIAN SMALL LETTER ENT, OLD HUNGARIAN CAPITAL LETTER ENT +test(0x10CE8, 0x10CA8); // OLD HUNGARIAN SMALL LETTER ETY, OLD HUNGARIAN CAPITAL LETTER ETY +test(0x10CE9, 0x10CA9); // OLD HUNGARIAN SMALL LETTER ECH, OLD HUNGARIAN CAPITAL LETTER ECH +test(0x10CEA, 0x10CAA); // OLD HUNGARIAN SMALL LETTER U, OLD HUNGARIAN CAPITAL LETTER U +test(0x10CEB, 0x10CAB); // OLD HUNGARIAN SMALL LETTER UU, OLD HUNGARIAN CAPITAL LETTER UU +test(0x10CEC, 0x10CAC); // OLD HUNGARIAN SMALL LETTER NIKOLSBURG UE, OLD HUNGARIAN CAPITAL LETTER NIKOLSBURG UE +test(0x10CED, 0x10CAD); // OLD HUNGARIAN SMALL LETTER RUDIMENTA UE, OLD HUNGARIAN CAPITAL LETTER RUDIMENTA UE +test(0x10CEE, 0x10CAE); // OLD HUNGARIAN SMALL LETTER EV, OLD HUNGARIAN CAPITAL LETTER EV +test(0x10CEF, 0x10CAF); // OLD HUNGARIAN SMALL LETTER EZ, OLD HUNGARIAN CAPITAL LETTER EZ +test(0x10CF0, 0x10CB0); // OLD HUNGARIAN SMALL LETTER EZS, OLD HUNGARIAN CAPITAL LETTER EZS +test(0x10CF1, 0x10CB1); // OLD HUNGARIAN SMALL LETTER ENT-SHAPED SIGN, OLD HUNGARIAN CAPITAL LETTER ENT-SHAPED SIGN +test(0x10CF2, 0x10CB2); // OLD HUNGARIAN SMALL LETTER US, OLD HUNGARIAN CAPITAL LETTER US +test(0x118A0, 0x118C0); // WARANG CITI CAPITAL LETTER NGAA, WARANG CITI SMALL LETTER NGAA +test(0x118A1, 0x118C1); // WARANG CITI CAPITAL LETTER A, WARANG CITI SMALL LETTER A +test(0x118A2, 0x118C2); // WARANG CITI CAPITAL LETTER WI, WARANG CITI SMALL LETTER WI +test(0x118A3, 0x118C3); // WARANG CITI CAPITAL LETTER YU, WARANG CITI SMALL LETTER YU +test(0x118A4, 0x118C4); // WARANG CITI CAPITAL LETTER YA, WARANG CITI SMALL LETTER YA +test(0x118A5, 0x118C5); // WARANG CITI CAPITAL LETTER YO, WARANG CITI SMALL LETTER YO +test(0x118A6, 0x118C6); // WARANG CITI CAPITAL LETTER II, WARANG CITI SMALL LETTER II +test(0x118A7, 0x118C7); // WARANG CITI CAPITAL LETTER UU, WARANG CITI SMALL LETTER UU +test(0x118A8, 0x118C8); // WARANG CITI CAPITAL LETTER E, WARANG CITI SMALL LETTER E +test(0x118A9, 0x118C9); // WARANG CITI CAPITAL LETTER O, WARANG CITI SMALL LETTER O +test(0x118AA, 0x118CA); // WARANG CITI CAPITAL LETTER ANG, WARANG CITI SMALL LETTER ANG +test(0x118AB, 0x118CB); // WARANG CITI CAPITAL LETTER GA, WARANG CITI SMALL LETTER GA +test(0x118AC, 0x118CC); // WARANG CITI CAPITAL LETTER KO, WARANG CITI SMALL LETTER KO +test(0x118AD, 0x118CD); // WARANG CITI CAPITAL LETTER ENY, WARANG CITI SMALL LETTER ENY +test(0x118AE, 0x118CE); // WARANG CITI CAPITAL LETTER YUJ, WARANG CITI SMALL LETTER YUJ +test(0x118AF, 0x118CF); // WARANG CITI CAPITAL LETTER UC, WARANG CITI SMALL LETTER UC +test(0x118B0, 0x118D0); // WARANG CITI CAPITAL LETTER ENN, WARANG CITI SMALL LETTER ENN +test(0x118B1, 0x118D1); // WARANG CITI CAPITAL LETTER ODD, WARANG CITI SMALL LETTER ODD +test(0x118B2, 0x118D2); // WARANG CITI CAPITAL LETTER TTE, WARANG CITI SMALL LETTER TTE +test(0x118B3, 0x118D3); // WARANG CITI CAPITAL LETTER NUNG, WARANG CITI SMALL LETTER NUNG +test(0x118B4, 0x118D4); // WARANG CITI CAPITAL LETTER DA, WARANG CITI SMALL LETTER DA +test(0x118B5, 0x118D5); // WARANG CITI CAPITAL LETTER AT, WARANG CITI SMALL LETTER AT +test(0x118B6, 0x118D6); // WARANG CITI CAPITAL LETTER AM, WARANG CITI SMALL LETTER AM +test(0x118B7, 0x118D7); // WARANG CITI CAPITAL LETTER BU, WARANG CITI SMALL LETTER BU +test(0x118B8, 0x118D8); // WARANG CITI CAPITAL LETTER PU, WARANG CITI SMALL LETTER PU +test(0x118B9, 0x118D9); // WARANG CITI CAPITAL LETTER HIYO, WARANG CITI SMALL LETTER HIYO +test(0x118BA, 0x118DA); // WARANG CITI CAPITAL LETTER HOLO, WARANG CITI SMALL LETTER HOLO +test(0x118BB, 0x118DB); // WARANG CITI CAPITAL LETTER HORR, WARANG CITI SMALL LETTER HORR +test(0x118BC, 0x118DC); // WARANG CITI CAPITAL LETTER HAR, WARANG CITI SMALL LETTER HAR +test(0x118BD, 0x118DD); // WARANG CITI CAPITAL LETTER SSUU, WARANG CITI SMALL LETTER SSUU +test(0x118BE, 0x118DE); // WARANG CITI CAPITAL LETTER SII, WARANG CITI SMALL LETTER SII +test(0x118BF, 0x118DF); // WARANG CITI CAPITAL LETTER VIYO, WARANG CITI SMALL LETTER VIYO +test(0x118C0, 0x118A0); // WARANG CITI SMALL LETTER NGAA, WARANG CITI CAPITAL LETTER NGAA +test(0x118C1, 0x118A1); // WARANG CITI SMALL LETTER A, WARANG CITI CAPITAL LETTER A +test(0x118C2, 0x118A2); // WARANG CITI SMALL LETTER WI, WARANG CITI CAPITAL LETTER WI +test(0x118C3, 0x118A3); // WARANG CITI SMALL LETTER YU, WARANG CITI CAPITAL LETTER YU +test(0x118C4, 0x118A4); // WARANG CITI SMALL LETTER YA, WARANG CITI CAPITAL LETTER YA +test(0x118C5, 0x118A5); // WARANG CITI SMALL LETTER YO, WARANG CITI CAPITAL LETTER YO +test(0x118C6, 0x118A6); // WARANG CITI SMALL LETTER II, WARANG CITI CAPITAL LETTER II +test(0x118C7, 0x118A7); // WARANG CITI SMALL LETTER UU, WARANG CITI CAPITAL LETTER UU +test(0x118C8, 0x118A8); // WARANG CITI SMALL LETTER E, WARANG CITI CAPITAL LETTER E +test(0x118C9, 0x118A9); // WARANG CITI SMALL LETTER O, WARANG CITI CAPITAL LETTER O +test(0x118CA, 0x118AA); // WARANG CITI SMALL LETTER ANG, WARANG CITI CAPITAL LETTER ANG +test(0x118CB, 0x118AB); // WARANG CITI SMALL LETTER GA, WARANG CITI CAPITAL LETTER GA +test(0x118CC, 0x118AC); // WARANG CITI SMALL LETTER KO, WARANG CITI CAPITAL LETTER KO +test(0x118CD, 0x118AD); // WARANG CITI SMALL LETTER ENY, WARANG CITI CAPITAL LETTER ENY +test(0x118CE, 0x118AE); // WARANG CITI SMALL LETTER YUJ, WARANG CITI CAPITAL LETTER YUJ +test(0x118CF, 0x118AF); // WARANG CITI SMALL LETTER UC, WARANG CITI CAPITAL LETTER UC +test(0x118D0, 0x118B0); // WARANG CITI SMALL LETTER ENN, WARANG CITI CAPITAL LETTER ENN +test(0x118D1, 0x118B1); // WARANG CITI SMALL LETTER ODD, WARANG CITI CAPITAL LETTER ODD +test(0x118D2, 0x118B2); // WARANG CITI SMALL LETTER TTE, WARANG CITI CAPITAL LETTER TTE +test(0x118D3, 0x118B3); // WARANG CITI SMALL LETTER NUNG, WARANG CITI CAPITAL LETTER NUNG +test(0x118D4, 0x118B4); // WARANG CITI SMALL LETTER DA, WARANG CITI CAPITAL LETTER DA +test(0x118D5, 0x118B5); // WARANG CITI SMALL LETTER AT, WARANG CITI CAPITAL LETTER AT +test(0x118D6, 0x118B6); // WARANG CITI SMALL LETTER AM, WARANG CITI CAPITAL LETTER AM +test(0x118D7, 0x118B7); // WARANG CITI SMALL LETTER BU, WARANG CITI CAPITAL LETTER BU +test(0x118D8, 0x118B8); // WARANG CITI SMALL LETTER PU, WARANG CITI CAPITAL LETTER PU +test(0x118D9, 0x118B9); // WARANG CITI SMALL LETTER HIYO, WARANG CITI CAPITAL LETTER HIYO +test(0x118DA, 0x118BA); // WARANG CITI SMALL LETTER HOLO, WARANG CITI CAPITAL LETTER HOLO +test(0x118DB, 0x118BB); // WARANG CITI SMALL LETTER HORR, WARANG CITI CAPITAL LETTER HORR +test(0x118DC, 0x118BC); // WARANG CITI SMALL LETTER HAR, WARANG CITI CAPITAL LETTER HAR +test(0x118DD, 0x118BD); // WARANG CITI SMALL LETTER SSUU, WARANG CITI CAPITAL LETTER SSUU +test(0x118DE, 0x118BE); // WARANG CITI SMALL LETTER SII, WARANG CITI CAPITAL LETTER SII +test(0x118DF, 0x118BF); // WARANG CITI SMALL LETTER VIYO, WARANG CITI CAPITAL LETTER VIYO +test(0x16E40, 0x16E60); // MEDEFAIDRIN CAPITAL LETTER M, MEDEFAIDRIN SMALL LETTER M +test(0x16E41, 0x16E61); // MEDEFAIDRIN CAPITAL LETTER S, MEDEFAIDRIN SMALL LETTER S +test(0x16E42, 0x16E62); // MEDEFAIDRIN CAPITAL LETTER V, MEDEFAIDRIN SMALL LETTER V +test(0x16E43, 0x16E63); // MEDEFAIDRIN CAPITAL LETTER W, MEDEFAIDRIN SMALL LETTER W +test(0x16E44, 0x16E64); // MEDEFAIDRIN CAPITAL LETTER ATIU, MEDEFAIDRIN SMALL LETTER ATIU +test(0x16E45, 0x16E65); // MEDEFAIDRIN CAPITAL LETTER Z, MEDEFAIDRIN SMALL LETTER Z +test(0x16E46, 0x16E66); // MEDEFAIDRIN CAPITAL LETTER KP, MEDEFAIDRIN SMALL LETTER KP +test(0x16E47, 0x16E67); // MEDEFAIDRIN CAPITAL LETTER P, MEDEFAIDRIN SMALL LETTER P +test(0x16E48, 0x16E68); // MEDEFAIDRIN CAPITAL LETTER T, MEDEFAIDRIN SMALL LETTER T +test(0x16E49, 0x16E69); // MEDEFAIDRIN CAPITAL LETTER G, MEDEFAIDRIN SMALL LETTER G +test(0x16E4A, 0x16E6A); // MEDEFAIDRIN CAPITAL LETTER F, MEDEFAIDRIN SMALL LETTER F +test(0x16E4B, 0x16E6B); // MEDEFAIDRIN CAPITAL LETTER I, MEDEFAIDRIN SMALL LETTER I +test(0x16E4C, 0x16E6C); // MEDEFAIDRIN CAPITAL LETTER K, MEDEFAIDRIN SMALL LETTER K +test(0x16E4D, 0x16E6D); // MEDEFAIDRIN CAPITAL LETTER A, MEDEFAIDRIN SMALL LETTER A +test(0x16E4E, 0x16E6E); // MEDEFAIDRIN CAPITAL LETTER J, MEDEFAIDRIN SMALL LETTER J +test(0x16E4F, 0x16E6F); // MEDEFAIDRIN CAPITAL LETTER E, MEDEFAIDRIN SMALL LETTER E +test(0x16E50, 0x16E70); // MEDEFAIDRIN CAPITAL LETTER B, MEDEFAIDRIN SMALL LETTER B +test(0x16E51, 0x16E71); // MEDEFAIDRIN CAPITAL LETTER C, MEDEFAIDRIN SMALL LETTER C +test(0x16E52, 0x16E72); // MEDEFAIDRIN CAPITAL LETTER U, MEDEFAIDRIN SMALL LETTER U +test(0x16E53, 0x16E73); // MEDEFAIDRIN CAPITAL LETTER YU, MEDEFAIDRIN SMALL LETTER YU +test(0x16E54, 0x16E74); // MEDEFAIDRIN CAPITAL LETTER L, MEDEFAIDRIN SMALL LETTER L +test(0x16E55, 0x16E75); // MEDEFAIDRIN CAPITAL LETTER Q, MEDEFAIDRIN SMALL LETTER Q +test(0x16E56, 0x16E76); // MEDEFAIDRIN CAPITAL LETTER HP, MEDEFAIDRIN SMALL LETTER HP +test(0x16E57, 0x16E77); // MEDEFAIDRIN CAPITAL LETTER NY, MEDEFAIDRIN SMALL LETTER NY +test(0x16E58, 0x16E78); // MEDEFAIDRIN CAPITAL LETTER X, MEDEFAIDRIN SMALL LETTER X +test(0x16E59, 0x16E79); // MEDEFAIDRIN CAPITAL LETTER D, MEDEFAIDRIN SMALL LETTER D +test(0x16E5A, 0x16E7A); // MEDEFAIDRIN CAPITAL LETTER OE, MEDEFAIDRIN SMALL LETTER OE +test(0x16E5B, 0x16E7B); // MEDEFAIDRIN CAPITAL LETTER N, MEDEFAIDRIN SMALL LETTER N +test(0x16E5C, 0x16E7C); // MEDEFAIDRIN CAPITAL LETTER R, MEDEFAIDRIN SMALL LETTER R +test(0x16E5D, 0x16E7D); // MEDEFAIDRIN CAPITAL LETTER O, MEDEFAIDRIN SMALL LETTER O +test(0x16E5E, 0x16E7E); // MEDEFAIDRIN CAPITAL LETTER AI, MEDEFAIDRIN SMALL LETTER AI +test(0x16E5F, 0x16E7F); // MEDEFAIDRIN CAPITAL LETTER Y, MEDEFAIDRIN SMALL LETTER Y +test(0x16E60, 0x16E40); // MEDEFAIDRIN SMALL LETTER M, MEDEFAIDRIN CAPITAL LETTER M +test(0x16E61, 0x16E41); // MEDEFAIDRIN SMALL LETTER S, MEDEFAIDRIN CAPITAL LETTER S +test(0x16E62, 0x16E42); // MEDEFAIDRIN SMALL LETTER V, MEDEFAIDRIN CAPITAL LETTER V +test(0x16E63, 0x16E43); // MEDEFAIDRIN SMALL LETTER W, MEDEFAIDRIN CAPITAL LETTER W +test(0x16E64, 0x16E44); // MEDEFAIDRIN SMALL LETTER ATIU, MEDEFAIDRIN CAPITAL LETTER ATIU +test(0x16E65, 0x16E45); // MEDEFAIDRIN SMALL LETTER Z, MEDEFAIDRIN CAPITAL LETTER Z +test(0x16E66, 0x16E46); // MEDEFAIDRIN SMALL LETTER KP, MEDEFAIDRIN CAPITAL LETTER KP +test(0x16E67, 0x16E47); // MEDEFAIDRIN SMALL LETTER P, MEDEFAIDRIN CAPITAL LETTER P +test(0x16E68, 0x16E48); // MEDEFAIDRIN SMALL LETTER T, MEDEFAIDRIN CAPITAL LETTER T +test(0x16E69, 0x16E49); // MEDEFAIDRIN SMALL LETTER G, MEDEFAIDRIN CAPITAL LETTER G +test(0x16E6A, 0x16E4A); // MEDEFAIDRIN SMALL LETTER F, MEDEFAIDRIN CAPITAL LETTER F +test(0x16E6B, 0x16E4B); // MEDEFAIDRIN SMALL LETTER I, MEDEFAIDRIN CAPITAL LETTER I +test(0x16E6C, 0x16E4C); // MEDEFAIDRIN SMALL LETTER K, MEDEFAIDRIN CAPITAL LETTER K +test(0x16E6D, 0x16E4D); // MEDEFAIDRIN SMALL LETTER A, MEDEFAIDRIN CAPITAL LETTER A +test(0x16E6E, 0x16E4E); // MEDEFAIDRIN SMALL LETTER J, MEDEFAIDRIN CAPITAL LETTER J +test(0x16E6F, 0x16E4F); // MEDEFAIDRIN SMALL LETTER E, MEDEFAIDRIN CAPITAL LETTER E +test(0x16E70, 0x16E50); // MEDEFAIDRIN SMALL LETTER B, MEDEFAIDRIN CAPITAL LETTER B +test(0x16E71, 0x16E51); // MEDEFAIDRIN SMALL LETTER C, MEDEFAIDRIN CAPITAL LETTER C +test(0x16E72, 0x16E52); // MEDEFAIDRIN SMALL LETTER U, MEDEFAIDRIN CAPITAL LETTER U +test(0x16E73, 0x16E53); // MEDEFAIDRIN SMALL LETTER YU, MEDEFAIDRIN CAPITAL LETTER YU +test(0x16E74, 0x16E54); // MEDEFAIDRIN SMALL LETTER L, MEDEFAIDRIN CAPITAL LETTER L +test(0x16E75, 0x16E55); // MEDEFAIDRIN SMALL LETTER Q, MEDEFAIDRIN CAPITAL LETTER Q +test(0x16E76, 0x16E56); // MEDEFAIDRIN SMALL LETTER HP, MEDEFAIDRIN CAPITAL LETTER HP +test(0x16E77, 0x16E57); // MEDEFAIDRIN SMALL LETTER NY, MEDEFAIDRIN CAPITAL LETTER NY +test(0x16E78, 0x16E58); // MEDEFAIDRIN SMALL LETTER X, MEDEFAIDRIN CAPITAL LETTER X +test(0x16E79, 0x16E59); // MEDEFAIDRIN SMALL LETTER D, MEDEFAIDRIN CAPITAL LETTER D +test(0x16E7A, 0x16E5A); // MEDEFAIDRIN SMALL LETTER OE, MEDEFAIDRIN CAPITAL LETTER OE +test(0x16E7B, 0x16E5B); // MEDEFAIDRIN SMALL LETTER N, MEDEFAIDRIN CAPITAL LETTER N +test(0x16E7C, 0x16E5C); // MEDEFAIDRIN SMALL LETTER R, MEDEFAIDRIN CAPITAL LETTER R +test(0x16E7D, 0x16E5D); // MEDEFAIDRIN SMALL LETTER O, MEDEFAIDRIN CAPITAL LETTER O +test(0x16E7E, 0x16E5E); // MEDEFAIDRIN SMALL LETTER AI, MEDEFAIDRIN CAPITAL LETTER AI +test(0x16E7F, 0x16E5F); // MEDEFAIDRIN SMALL LETTER Y, MEDEFAIDRIN CAPITAL LETTER Y +test(0x1E900, 0x1E922); // ADLAM CAPITAL LETTER ALIF, ADLAM SMALL LETTER ALIF +test(0x1E901, 0x1E923); // ADLAM CAPITAL LETTER DAALI, ADLAM SMALL LETTER DAALI +test(0x1E902, 0x1E924); // ADLAM CAPITAL LETTER LAAM, ADLAM SMALL LETTER LAAM +test(0x1E903, 0x1E925); // ADLAM CAPITAL LETTER MIIM, ADLAM SMALL LETTER MIIM +test(0x1E904, 0x1E926); // ADLAM CAPITAL LETTER BA, ADLAM SMALL LETTER BA +test(0x1E905, 0x1E927); // ADLAM CAPITAL LETTER SINNYIIYHE, ADLAM SMALL LETTER SINNYIIYHE +test(0x1E906, 0x1E928); // ADLAM CAPITAL LETTER PE, ADLAM SMALL LETTER PE +test(0x1E907, 0x1E929); // ADLAM CAPITAL LETTER BHE, ADLAM SMALL LETTER BHE +test(0x1E908, 0x1E92A); // ADLAM CAPITAL LETTER RA, ADLAM SMALL LETTER RA +test(0x1E909, 0x1E92B); // ADLAM CAPITAL LETTER E, ADLAM SMALL LETTER E +test(0x1E90A, 0x1E92C); // ADLAM CAPITAL LETTER FA, ADLAM SMALL LETTER FA +test(0x1E90B, 0x1E92D); // ADLAM CAPITAL LETTER I, ADLAM SMALL LETTER I +test(0x1E90C, 0x1E92E); // ADLAM CAPITAL LETTER O, ADLAM SMALL LETTER O +test(0x1E90D, 0x1E92F); // ADLAM CAPITAL LETTER DHA, ADLAM SMALL LETTER DHA +test(0x1E90E, 0x1E930); // ADLAM CAPITAL LETTER YHE, ADLAM SMALL LETTER YHE +test(0x1E90F, 0x1E931); // ADLAM CAPITAL LETTER WAW, ADLAM SMALL LETTER WAW +test(0x1E910, 0x1E932); // ADLAM CAPITAL LETTER NUN, ADLAM SMALL LETTER NUN +test(0x1E911, 0x1E933); // ADLAM CAPITAL LETTER KAF, ADLAM SMALL LETTER KAF +test(0x1E912, 0x1E934); // ADLAM CAPITAL LETTER YA, ADLAM SMALL LETTER YA +test(0x1E913, 0x1E935); // ADLAM CAPITAL LETTER U, ADLAM SMALL LETTER U +test(0x1E914, 0x1E936); // ADLAM CAPITAL LETTER JIIM, ADLAM SMALL LETTER JIIM +test(0x1E915, 0x1E937); // ADLAM CAPITAL LETTER CHI, ADLAM SMALL LETTER CHI +test(0x1E916, 0x1E938); // ADLAM CAPITAL LETTER HA, ADLAM SMALL LETTER HA +test(0x1E917, 0x1E939); // ADLAM CAPITAL LETTER QAAF, ADLAM SMALL LETTER QAAF +test(0x1E918, 0x1E93A); // ADLAM CAPITAL LETTER GA, ADLAM SMALL LETTER GA +test(0x1E919, 0x1E93B); // ADLAM CAPITAL LETTER NYA, ADLAM SMALL LETTER NYA +test(0x1E91A, 0x1E93C); // ADLAM CAPITAL LETTER TU, ADLAM SMALL LETTER TU +test(0x1E91B, 0x1E93D); // ADLAM CAPITAL LETTER NHA, ADLAM SMALL LETTER NHA +test(0x1E91C, 0x1E93E); // ADLAM CAPITAL LETTER VA, ADLAM SMALL LETTER VA +test(0x1E91D, 0x1E93F); // ADLAM CAPITAL LETTER KHA, ADLAM SMALL LETTER KHA +test(0x1E91E, 0x1E940); // ADLAM CAPITAL LETTER GBE, ADLAM SMALL LETTER GBE +test(0x1E91F, 0x1E941); // ADLAM CAPITAL LETTER ZAL, ADLAM SMALL LETTER ZAL +test(0x1E920, 0x1E942); // ADLAM CAPITAL LETTER KPO, ADLAM SMALL LETTER KPO +test(0x1E921, 0x1E943); // ADLAM CAPITAL LETTER SHA, ADLAM SMALL LETTER SHA +test(0x1E922, 0x1E900); // ADLAM SMALL LETTER ALIF, ADLAM CAPITAL LETTER ALIF +test(0x1E923, 0x1E901); // ADLAM SMALL LETTER DAALI, ADLAM CAPITAL LETTER DAALI +test(0x1E924, 0x1E902); // ADLAM SMALL LETTER LAAM, ADLAM CAPITAL LETTER LAAM +test(0x1E925, 0x1E903); // ADLAM SMALL LETTER MIIM, ADLAM CAPITAL LETTER MIIM +test(0x1E926, 0x1E904); // ADLAM SMALL LETTER BA, ADLAM CAPITAL LETTER BA +test(0x1E927, 0x1E905); // ADLAM SMALL LETTER SINNYIIYHE, ADLAM CAPITAL LETTER SINNYIIYHE +test(0x1E928, 0x1E906); // ADLAM SMALL LETTER PE, ADLAM CAPITAL LETTER PE +test(0x1E929, 0x1E907); // ADLAM SMALL LETTER BHE, ADLAM CAPITAL LETTER BHE +test(0x1E92A, 0x1E908); // ADLAM SMALL LETTER RA, ADLAM CAPITAL LETTER RA +test(0x1E92B, 0x1E909); // ADLAM SMALL LETTER E, ADLAM CAPITAL LETTER E +test(0x1E92C, 0x1E90A); // ADLAM SMALL LETTER FA, ADLAM CAPITAL LETTER FA +test(0x1E92D, 0x1E90B); // ADLAM SMALL LETTER I, ADLAM CAPITAL LETTER I +test(0x1E92E, 0x1E90C); // ADLAM SMALL LETTER O, ADLAM CAPITAL LETTER O +test(0x1E92F, 0x1E90D); // ADLAM SMALL LETTER DHA, ADLAM CAPITAL LETTER DHA +test(0x1E930, 0x1E90E); // ADLAM SMALL LETTER YHE, ADLAM CAPITAL LETTER YHE +test(0x1E931, 0x1E90F); // ADLAM SMALL LETTER WAW, ADLAM CAPITAL LETTER WAW +test(0x1E932, 0x1E910); // ADLAM SMALL LETTER NUN, ADLAM CAPITAL LETTER NUN +test(0x1E933, 0x1E911); // ADLAM SMALL LETTER KAF, ADLAM CAPITAL LETTER KAF +test(0x1E934, 0x1E912); // ADLAM SMALL LETTER YA, ADLAM CAPITAL LETTER YA +test(0x1E935, 0x1E913); // ADLAM SMALL LETTER U, ADLAM CAPITAL LETTER U +test(0x1E936, 0x1E914); // ADLAM SMALL LETTER JIIM, ADLAM CAPITAL LETTER JIIM +test(0x1E937, 0x1E915); // ADLAM SMALL LETTER CHI, ADLAM CAPITAL LETTER CHI +test(0x1E938, 0x1E916); // ADLAM SMALL LETTER HA, ADLAM CAPITAL LETTER HA +test(0x1E939, 0x1E917); // ADLAM SMALL LETTER QAAF, ADLAM CAPITAL LETTER QAAF +test(0x1E93A, 0x1E918); // ADLAM SMALL LETTER GA, ADLAM CAPITAL LETTER GA +test(0x1E93B, 0x1E919); // ADLAM SMALL LETTER NYA, ADLAM CAPITAL LETTER NYA +test(0x1E93C, 0x1E91A); // ADLAM SMALL LETTER TU, ADLAM CAPITAL LETTER TU +test(0x1E93D, 0x1E91B); // ADLAM SMALL LETTER NHA, ADLAM CAPITAL LETTER NHA +test(0x1E93E, 0x1E91C); // ADLAM SMALL LETTER VA, ADLAM CAPITAL LETTER VA +test(0x1E93F, 0x1E91D); // ADLAM SMALL LETTER KHA, ADLAM CAPITAL LETTER KHA +test(0x1E940, 0x1E91E); // ADLAM SMALL LETTER GBE, ADLAM CAPITAL LETTER GBE +test(0x1E941, 0x1E91F); // ADLAM SMALL LETTER ZAL, ADLAM CAPITAL LETTER ZAL +test(0x1E942, 0x1E920); // ADLAM SMALL LETTER KPO, ADLAM CAPITAL LETTER KPO +test(0x1E943, 0x1E921); // ADLAM SMALL LETTER SHA, ADLAM CAPITAL LETTER SHA + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/unicode-index.js b/js/src/tests/non262/RegExp/unicode-index.js new file mode 100644 index 0000000000..a4b2eb2030 --- /dev/null +++ b/js/src/tests/non262/RegExp/unicode-index.js @@ -0,0 +1,17 @@ +var BUGNUMBER = 1135377; +var summary = "Implement RegExp unicode flag -- Pattern match should start from lead surrogate when lastIndex points corresponding trail surrogate."; + +print(BUGNUMBER + ": " + summary); + +var r = /\uD83D\uDC38/ug; +r.lastIndex = 1; +var str = "\uD83D\uDC38"; +var result = r.exec(str); +assertEq(result.length, 1); +assertEq(result[0], "\uD83D\uDC38"); + +// This does not match to ES6 spec, but the spec will be changed. +assertEq(result.index, 0); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/unicode-lead-trail.js b/js/src/tests/non262/RegExp/unicode-lead-trail.js new file mode 100644 index 0000000000..7ecdb9ace4 --- /dev/null +++ b/js/src/tests/non262/RegExp/unicode-lead-trail.js @@ -0,0 +1,218 @@ +var BUGNUMBER = 1135377; +var summary = "Implement RegExp unicode flag -- lead and trail patterns in RegExpUnicodeEscapeSequence."; + +print(BUGNUMBER + ": " + summary); + +// ==== standalone ==== + +assertEqArray(/\uD83D\uDC38/u.exec("\u{1F438}"), + ["\u{1F438}"]); + +// no unicode flag +assertEqArray(/\uD83D\uDC38/.exec("\u{1F438}"), + ["\u{1F438}"]); + +// RegExp constructor +assertEqArray(new RegExp("\\uD83D\\uDC38", "u").exec("\u{1F438}"), + ["\u{1F438}"]); + +// RegExp constructor, no unicode flag +assertEqArray(new RegExp("\\uD83D\\uDC38", "").exec("\u{1F438}"), + ["\u{1F438}"]); + +// ==== ? ==== + +assertEqArray(/\uD83D\uDC38?/u.exec("\u{1F438}"), + ["\u{1F438}"]); +assertEqArray(/\uD83D\uDC38?/u.exec(""), + [""]); + +// lead-only target +assertEqArray(/\uD83D\uDC38?/u.exec("\uD83D"), + [""]); + +// no unicode flag +assertEqArray(/\uD83D\uDC38?/.exec("\u{1F438}"), + ["\u{1F438}"]); +assertEq(/\uD83D\uDC38?/.exec(""), + null); + +assertEqArray(/\uD83D\uDC38?/.exec("\uD83D"), + ["\uD83D"]); + +// RegExp constructor +assertEqArray(new RegExp("\\uD83D\\uDC38?", "u").exec("\u{1F438}"), + ["\u{1F438}"]); +assertEqArray(new RegExp("\\uD83D\\uDC38?", "u").exec(""), + [""]); + +assertEqArray(new RegExp("\\uD83D\\uDC38?", "u").exec("\uD83D"), + [""]); + +// RegExp constructor, no unicode flag +assertEqArray(new RegExp("\\uD83D\\uDC38?", "").exec("\u{1F438}"), + ["\u{1F438}"]); +assertEq(new RegExp("\\uD83D\\uDC38?", "").exec(""), + null); + +assertEqArray(new RegExp("\\uD83D\\uDC38?", "").exec("\uD83D"), + ["\uD83D"]); + +// ==== + ==== + +assertEqArray(/\uD83D\uDC38+/u.exec("\u{1F438}"), + ["\u{1F438}"]); +assertEqArray(/\uD83D\uDC38+/u.exec("\u{1F438}\u{1F438}"), + ["\u{1F438}\u{1F438}"]); +assertEq(/\uD83D\uDC38+/u.exec(""), + null); + +// lead-only target +assertEq(/\uD83D\uDC38+/u.exec("\uD83D"), + null); +assertEqArray(/\uD83D\uDC38+/u.exec("\uD83D\uDC38\uDC38"), + ["\uD83D\uDC38"]); + +// no unicode flag +assertEqArray(/\uD83D\uDC38+/.exec("\u{1F438}"), + ["\u{1F438}"]); +assertEqArray(/\uD83D\uDC38+/.exec("\u{1F438}\u{1F438}"), + ["\u{1F438}"]); +assertEq(/\uD83D\uDC38+/.exec("\uD83D"), + null); +assertEqArray(/\uD83D\uDC38+/.exec("\uD83D\uDC38\uDC38"), + ["\uD83D\uDC38\uDC38"]); +assertEq(/\uD83D\uDC38+/.exec(""), + null); + +// ==== * ==== + +assertEqArray(/\uD83D\uDC38*/u.exec("\u{1F438}"), + ["\u{1F438}"]); +assertEqArray(/\uD83D\uDC38*/u.exec("\u{1F438}\u{1F438}"), + ["\u{1F438}\u{1F438}"]); +assertEqArray(/\uD83D\uDC38*/u.exec(""), + [""]); + +// lead-only target +assertEqArray(/\uD83D\uDC38*/u.exec("\uD83D"), + [""]); +assertEqArray(/\uD83D\uDC38*/u.exec("\uD83D\uDC38\uDC38"), + ["\uD83D\uDC38"]); + +// no unicode flag +assertEqArray(/\uD83D\uDC38*/.exec("\u{1F438}"), + ["\u{1F438}"]); +assertEqArray(/\uD83D\uDC38*/.exec("\u{1F438}\u{1F438}"), + ["\u{1F438}"]); +assertEqArray(/\uD83D\uDC38*/.exec("\uD83D"), + ["\uD83D"]); +assertEqArray(/\uD83D\uDC38*/.exec("\uD83D\uDC38\uDC38"), + ["\uD83D\uDC38\uDC38"]); +assertEq(/\uD83D\uDC38*/.exec(""), + null); + +// ==== lead-only ==== + +// match only non-surrogate pair +assertEqArray(/\uD83D/u.exec("\uD83D\uDBFF"), + ["\uD83D"]); +assertEq(/\uD83D/u.exec("\uD83D\uDC00"), + null); +assertEq(/\uD83D/u.exec("\uD83D\uDFFF"), + null); +assertEqArray(/\uD83D/u.exec("\uD83D\uE000"), + ["\uD83D"]); + +// match before non-tail char +assertEqArray(/\uD83D/u.exec("\uD83D"), + ["\uD83D"]); +assertEqArray(/\uD83D/u.exec("\uD83DA"), + ["\uD83D"]); + +// no unicode flag +assertEqArray(/\uD83D/.exec("\uD83D\uDBFF"), + ["\uD83D"]); +assertEqArray(/\uD83D/.exec("\uD83D\uDC00"), + ["\uD83D"]); +assertEqArray(/\uD83D/.exec("\uD83D\uDFFF"), + ["\uD83D"]); +assertEqArray(/\uD83D/.exec("\uD83D\uE000"), + ["\uD83D"]); +assertEqArray(/\uD83D/.exec("\uD83D"), + ["\uD83D"]); +assertEqArray(/\uD83D/.exec("\uD83DA"), + ["\uD83D"]); + +// ==== trail-only ==== + +// match only non-surrogate pair +assertEqArray(/\uDC38/u.exec("\uD7FF\uDC38"), + ["\uDC38"]); +assertEq(/\uDC38/u.exec("\uD800\uDC38"), + null); +assertEq(/\uDC38/u.exec("\uDBFF\uDC38"), + null); +assertEqArray(/\uDC38/u.exec("\uDC00\uDC38"), + ["\uDC38"]); + +// match after non-lead char +assertEqArray(/\uDC38/u.exec("\uDC38"), + ["\uDC38"]); +assertEqArray(/\uDC38/u.exec("A\uDC38"), + ["\uDC38"]); + +// no unicode flag +assertEqArray(/\uDC38/.exec("\uD7FF\uDC38"), + ["\uDC38"]); +assertEqArray(/\uDC38/.exec("\uD800\uDC38"), + ["\uDC38"]); +assertEqArray(/\uDC38/.exec("\uDBFF\uDC38"), + ["\uDC38"]); +assertEqArray(/\uDC38/.exec("\uDC00\uDC38"), + ["\uDC38"]); +assertEqArray(/\uDC38/.exec("\uDC38"), + ["\uDC38"]); +assertEqArray(/\uDC38/.exec("A\uDC38"), + ["\uDC38"]); + +// ==== invalid trail ==== + +assertEqArray(/\uD83D\u3042*/u.exec("\uD83D"), + ["\uD83D"]); +assertEqArray(/\uD83D\u3042*/u.exec("\uD83D\u3042"), + ["\uD83D\u3042"]); +assertEqArray(/\uD83D\u3042*/u.exec("\uD83D\u3042\u3042"), + ["\uD83D\u3042\u3042"]); + +assertEqArray(/\uD83D\u{3042}*/u.exec("\uD83D"), + ["\uD83D"]); +assertEqArray(/\uD83D\u{3042}*/u.exec("\uD83D\u3042"), + ["\uD83D\u3042"]); +assertEqArray(/\uD83D\u{3042}*/u.exec("\uD83D\u3042\u3042"), + ["\uD83D\u3042\u3042"]); + +assertEqArray(/\uD83DA*/u.exec("\uD83D"), + ["\uD83D"]); +assertEqArray(/\uD83DA*/u.exec("\uD83DA"), + ["\uD83DA"]); +assertEqArray(/\uD83DA*/u.exec("\uD83DAA"), + ["\uD83DAA"]); + +// ==== wrong patterns ==== + +assertThrowsInstanceOf(() => eval(`/\\u/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\u0/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\u00/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\u000/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\u000G/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\u0.00/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\uD83D\\u/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\uD83D\\u0/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\uD83D\\u00/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\uD83D\\u000/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\uD83D\\u000G/u`), SyntaxError); +assertThrowsInstanceOf(() => eval(`/\\uD83D\\u0.00/u`), SyntaxError); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/unicode-raw.js b/js/src/tests/non262/RegExp/unicode-raw.js new file mode 100644 index 0000000000..37b572cd82 --- /dev/null +++ b/js/src/tests/non262/RegExp/unicode-raw.js @@ -0,0 +1,139 @@ +var BUGNUMBER = 1135377; +var summary = "Implement RegExp unicode flag -- raw unicode."; + +print(BUGNUMBER + ": " + summary); + +// ==== standalone ==== + +assertEqArray(eval(`/\uD83D\uDC38/u`).exec("\u{1F438}"), + ["\u{1F438}"]); + +// no unicode flag +assertEqArray(eval(`/\uD83D\uDC38/`).exec("\u{1F438}"), + ["\u{1F438}"]); + +// escaped (lead) +assertEq(eval(`/\\uD83D\uDC38/u`).exec("\u{1F438}"), + null); +assertEq(eval(`/\\u{D83D}\uDC38/u`).exec("\u{1F438}"), + null); + +// escaped (trail) +assertEq(eval(`/\uD83D\\uDC38/u`).exec("\u{1F438}"), + null); +assertEq(eval(`/\uD83D\\u{DC38}/u`).exec("\u{1F438}"), + null); + +// escaped (lead), no unicode flag +assertEqArray(eval(`/\\uD83D\uDC38/`).exec("\u{1F438}"), + ["\u{1F438}"]); + +// escaped (trail), no unicode flag +assertEqArray(eval(`/\uD83D\\uDC38/`).exec("\u{1F438}"), + ["\u{1F438}"]); + +// ==== RegExp constructor ==== + +assertEqArray(new RegExp("\uD83D\uDC38", "u").exec("\u{1F438}"), + ["\u{1F438}"]); + +// no unicode flag +assertEqArray(new RegExp("\uD83D\uDC38", "").exec("\u{1F438}"), + ["\u{1F438}"]); + +// escaped(lead) +assertEq(new RegExp("\\uD83D\uDC38", "u").exec("\u{1F438}"), + null); +assertEq(new RegExp("\\u{D83D}\uDC38", "u").exec("\u{1F438}"), + null); + +// escaped(trail) +assertEq(new RegExp("\uD83D\\uDC38", "u").exec("\u{1F438}"), + null); +assertEq(new RegExp("\uD83D\\u{DC38}", "u").exec("\u{1F438}"), + null); + +// escaped(lead), no unicode flag +assertEqArray(new RegExp("\\uD83D\uDC38", "").exec("\u{1F438}"), + ["\u{1F438}"]); + +// escaped(trail), no unicode flag +assertEqArray(new RegExp("\uD83D\\uDC38", "").exec("\u{1F438}"), + ["\u{1F438}"]); + +// ==== ? ==== + +assertEqArray(eval(`/\uD83D\uDC38?/u`).exec("\u{1F438}"), + ["\u{1F438}"]); +assertEqArray(eval(`/\uD83D\uDC38?/u`).exec(""), + [""]); + +assertEqArray(eval(`/\uD83D\uDC38?/u`).exec("\uD83D"), + [""]); + +// no unicode flag +assertEqArray(eval(`/\uD83D\uDC38?/`).exec("\u{1F438}"), + ["\u{1F438}"]); +assertEq(eval(`/\uD83D\uDC38?/`).exec(""), + null); + +assertEqArray(eval(`/\uD83D\uDC38?/`).exec("\uD83D"), + ["\uD83D"]); + +// escaped (lead) +assertEq(eval(`/\\uD83D\uDC38?/u`).exec("\u{1F438}"), + null); +assertEq(eval(`/\\uD83D\uDC38?/u`).exec(""), + null); + +assertEqArray(eval(`/\\uD83D\uDC38?/u`).exec("\uD83D"), + ["\uD83D"]); + +// escaped (trail) +assertEq(eval(`/\uD83D\\uDC38?/u`).exec("\u{1F438}"), + null); +assertEq(eval(`/\uD83D\\uDC38?/u`).exec(""), + null); + +assertEqArray(eval(`/\uD83D\\uDC38?/u`).exec("\uD83D"), + ["\uD83D"]); + +// escaped (lead), no unicode flag +assertEqArray(eval(`/\\uD83D\uDC38?/`).exec("\u{1F438}"), + ["\u{1F438}"]); +assertEq(eval(`/\\uD83D\uDC38?/`).exec(""), + null); + +assertEqArray(eval(`/\\uD83D\uDC38?/`).exec("\uD83D"), + ["\uD83D"]); + +// escaped (trail), no unicode flag +assertEqArray(eval(`/\uD83D\\uDC38?/`).exec("\u{1F438}"), + ["\u{1F438}"]); +assertEq(eval(`/\uD83D\\uDC38?/`).exec(""), + null); + +assertEqArray(eval(`/\uD83D\\uDC38?/`).exec("\uD83D"), + ["\uD83D"]); + +// ==== RegExp constructor, ? ==== + +assertEqArray(new RegExp("\uD83D\uDC38?", "u").exec("\u{1F438}"), + ["\u{1F438}"]); +assertEqArray(new RegExp("\uD83D\uDC38?", "u").exec(""), + [""]); + +assertEqArray(new RegExp("\uD83D\uDC38?", "u").exec("\uD83D"), + [""]); + +// no unicode flag +assertEqArray(new RegExp("\uD83D\uDC38?", "").exec("\u{1F438}"), + ["\u{1F438}"]); +assertEq(new RegExp("\uD83D\uDC38?", "").exec(""), + null); + +assertEqArray(new RegExp("\uD83D\uDC38?", "").exec("\uD83D"), + ["\uD83D"]); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/RegExp/yflag.js b/js/src/tests/non262/RegExp/yflag.js new file mode 100644 index 0000000000..db101c0b01 --- /dev/null +++ b/js/src/tests/non262/RegExp/yflag.js @@ -0,0 +1,85 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 371932; +var summary = 'ES4 Regular Expression /y flag'; +var actual = ''; +var expect = ''; + +print('See http://developer.mozilla.org/es4/proposals/extend_regexps.html#y_flag'); + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + var c; + var s = '123456'; + + print('Test global flag.'); + + var g = /(1)/g; + expect = 'captures: 1,1; RegExp.leftContext: ""; RegExp.rightContext: "234561"'; + actual = 'captures: ' + g.exec('1234561') + + '; RegExp.leftContext: "' + RegExp.leftContext + + '"; RegExp.rightContext: "' + RegExp.rightContext + '"'; + reportCompare(expect, actual, summary + ' - /(1)/g.exec("1234561") first call'); + + expect = 'captures: 1,1; RegExp.leftContext: "123456"; RegExp.rightContext: ""'; + actual = 'captures: ' + g.exec('1234561') + + '; RegExp.leftContext: "' + RegExp.leftContext + + '"; RegExp.rightContext: "' + RegExp.rightContext + '"'; + reportCompare(expect, actual, summary + ' - /(1)/g.exec("1234561") second call'); + var y = /(1)/y; + + print('Test sticky flag.'); + + /* + * calls to reportCompare invoke regular expression matches which interfere + * with the test of the sticky flag. Collect expect and actual values prior + * to calling reportCompare. Note setting y = /(1)/y resets the lastIndex etc. + */ + + var y = /(1)/y; + var expect4 = 'captures: 1,1; RegExp.leftContext: ""; RegExp.rightContext: "234561"'; + var actual4 = 'captures: ' + y.exec('1234561') + + '; RegExp.leftContext: "' + RegExp.leftContext + + '"; RegExp.rightContext: "' + RegExp.rightContext + '"'; + + var expect5 = 'captures: null; RegExp.leftContext: ""; RegExp.rightContext: "234561"'; + var actual5 = 'captures: ' + y.exec('1234561') + + '; RegExp.leftContext: "' + RegExp.leftContext + + '"; RegExp.rightContext: "' + RegExp.rightContext + '"'; + + reportCompare(expect4, actual4, summary + ' - /(1)/y.exec("1234561") first call'); + reportCompare(expect5, actual5, summary + ' - /(1)/y.exec("1234561") second call'); + + var y = /(1)/y; + + reportCompare(expect5, actual5, summary); + + y = /(1)/y; + var expect6 = 'captures: 1,1; RegExp.leftContext: ""; RegExp.rightContext: "123456"'; + var actual6 = 'captures: ' + y.exec('1123456') + + '; RegExp.leftContext: "' + RegExp.leftContext + + '"; RegExp.rightContext: "' + RegExp.rightContext + '"'; + + var expect7 = 'captures: 1,1; RegExp.leftContext: "1"; RegExp.rightContext: "23456"'; + var actual7 = 'captures: ' + y.exec('1123456') + + '; RegExp.leftContext: "' + RegExp.leftContext + + '"; RegExp.rightContext: "' + RegExp.rightContext + '"'; + + reportCompare(expect6, actual6, summary + ' - /(1)/y.exec("1123456") first call'); + reportCompare(expect7, actual7, summary + ' - /(1)/y.exec("1123456") second call'); + + var y = /(1)/y; + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/Scope/browser.js b/js/src/tests/non262/Scope/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Scope/regress-154693.js b/js/src/tests/non262/Scope/regress-154693.js new file mode 100644 index 0000000000..d0f0a5ea86 --- /dev/null +++ b/js/src/tests/non262/Scope/regress-154693.js @@ -0,0 +1,64 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * + * Date: 26 Nov 2002 + * SUMMARY: Testing scope + * See http://bugzilla.mozilla.org/show_bug.cgi?id=154693 + * + */ +//----------------------------------------------------------------------------- +var UBound = 0; +var BUGNUMBER = 154693; +var summary = 'Testing scope'; +var status = ''; +var statusitems = []; +var actual = ''; +var actualvalues = []; +var expect= ''; +var expectedvalues = []; + + +function f() +{ + function nested() {} + return nested; +} +var f1 = f(); +var f2 = f(); + +status = inSection(1); +actual = (f1 != f2); +expect = true; +addThis(); + + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + + +function addThis() +{ + statusitems[UBound] = status; + actualvalues[UBound] = actual; + expectedvalues[UBound] = expect; + UBound++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus(summary); + + for (var i=0; i0, we end up calling inner() N+1 times: + * inner(N), inner(N-1), ... , inner(0). + * + * Each call to inner() increments |outer_d| by 1. + * The last call, inner(0), returns the final value + * of |outer_d|, which should be N+1. + */ +function outer(N) +{ + var outer_d = 0; + return inner(N); + + function inner(level) + { + outer_d++; + + if (level > 0) + return inner(level - 1); + else + return outer_d; + } +} + + +/* + * This only has meaning in Rhino - + */ +setDynamicScope(true); + +/* + * Recompile the function |outer| via eval() in order to + * feel the effect of the dynamic scope mode we have set. + */ +var s = outer.toString(); +eval(s); + +status = inSection(1); +actual = outer(-5); +expect = 1; +addThis(); + +status = inSection(2); +actual = outer(0); +expect = 1; +addThis(); + +status = inSection(3); +actual = outer(5); +expect = 6; +addThis(); + + +/* + * Sanity check: do same steps with the dynamic flag off + */ +setDynamicScope(false); + +/* + * Recompile the function |outer| via eval() in order to + * feel the effect of the dynamic scope mode we have set. + */ +eval(s); + +status = inSection(4); +actual = outer(-5); +expect = 1; +addThis(); + +status = inSection(5); +actual = outer(0); +expect = 1; +addThis(); + +status = inSection(6); +actual = outer(5); +expect = 6; +addThis(); + + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + + +function setDynamicScope(flag) +{ + if (this.Packages) + { + var cx = this.Packages.org.mozilla.javascript.Context.getCurrentContext(); + cx.setCompileFunctionsWithDynamicScope(flag); + } +} + + +function addThis() +{ + statusitems[UBound] = status; + actualvalues[UBound] = actual; + expectedvalues[UBound] = expect; + UBound++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus(summary); + + for (var i=0; i

"; + sb[sb.length] = this.getNodeHtml(); + sb[sb.length] = this.getChildrenHtml(); +}; + +ygNode.prototype.getChildrenHtml = function () { + var sb = []; + if (this.hasChildren(true) && this.expanded) { + sb[sb.length] = this.renderChildren(); + } +}; + +ygNode.prototype.renderChildren = function () {return this.completeRender();}; + +ygNode.prototype.completeRender = function () { + var sb = []; + for (var i = 0; i < this.children.length; ++i) { + sb[sb.length] = this.children[i].getHtml(); + } +}; + +ygRootNode.prototype = new ygNode; + +function ygRootNode(_48) { + this.init(null, null, true); +} + +ygTextNode.prototype = new ygNode; + +function ygTextNode(_49, _50, _51) { + this.init(_49, _50, _51); + this.setUpLabel(_49); +} + +ygTextNode.prototype.setUpLabel = function (_52) { + if (typeof _52 == "string") {} + if (_52.target) {} + this.labelElId = "ygtvlabelel" + this.index; +}; + +ygTextNode.prototype.getNodeHtml = function () { + var sb = new Array; + sb[sb.length] = ""; + sb[sb.length] = ""; + for (i = 0; i < this.depth; ++i) {} + sb[sb.length] = " id=\"" + this.getToggleElId() + "\""; + sb[sb.length] = " class=\"" + this.getStyle() + "\""; + if (this.hasChildren(true)) {} + sb[sb.length] = " id=\"" + this.labelElId + "\""; +}; + +function buildUserTree() { + userTree = new ygTreeView("userTree"); + addMenuNode(userTree, "N", "navheader"); + addMenuNode(userTree, "R", "navheader"); + addMenuNode(userTree, "S", "navheader"); +} + +function addMenuNode(tree, label, styleClass) { + new ygTextNode({}, tree.root, false); +} + +buildUserTree(); +userTree.root.getHtml(); + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/regress/regress-464978.js b/js/src/tests/non262/regress/regress-464978.js new file mode 100644 index 0000000000..5fe2ae86ad --- /dev/null +++ b/js/src/tests/non262/regress/regress-464978.js @@ -0,0 +1,27 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 464978; +var summary = 'Do not hang with [] + null'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + + for (let j = 0; j < 2; ++j) { [] + null; } + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465013.js b/js/src/tests/non262/regress/regress-465013.js new file mode 100644 index 0000000000..de936645f2 --- /dev/null +++ b/js/src/tests/non262/regress/regress-465013.js @@ -0,0 +1,36 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465013; +var summary = ''; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + expect = 'bgcolor="dummy" quality="dummy" allowScriptAccess="dummy" '; + + + print((function(x) { + var ja = ""; + var ka = {bgcolor:"#FFFFFF", quality:"high", allowScriptAccess:"always"}; + for (var la in ka) { + ja +=[la] + "=\"" + x/*ka[la]*/ + "\" "; + } + return actual = ja; + })("dummy")); + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465132.js b/js/src/tests/non262/regress/regress-465132.js new file mode 100644 index 0000000000..7bb607411c --- /dev/null +++ b/js/src/tests/non262/regress/regress-465132.js @@ -0,0 +1,39 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465132; +var summary = 'TM: Mathematical constants should be constant'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + + var constants = ['E', 'LN10', 'LN2', 'LOG2E', 'LOG10E', 'PI', 'SQRT1_2', 'SQRT2']; + + for (var j = 0; j < constants.length; j++) + { + expect = Math[constants[j]]; + + for(i=0;i<9;++i) + ++Math[constants[j]]; + + for(i=0;i<9;++i) + eval('++Math.' + constants[j]); + + actual = Math[constants[j]]; + + reportCompare(expect, actual, summary + ' Math.' + constants[j]); + } +} diff --git a/js/src/tests/non262/regress/regress-465133.js b/js/src/tests/non262/regress/regress-465133.js new file mode 100644 index 0000000000..9fad075199 --- /dev/null +++ b/js/src/tests/non262/regress/regress-465133.js @@ -0,0 +1,30 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465133; +var summary = '{} < {}'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + expect = 'false,false,false,false,false,'; + actual = ''; + + + for (var i=0;i<5;++i) actual += ({} < {}) + ','; + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465135.js b/js/src/tests/non262/regress/regress-465135.js new file mode 100644 index 0000000000..4af87514c7 --- /dev/null +++ b/js/src/tests/non262/regress/regress-465135.js @@ -0,0 +1,30 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465135; +var summary = 'true << true'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + expect = '2,2,2,2,2,'; + actual = ''; + + + for (var i=0;i<5;++i) actual += (true << true) + ','; + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465136.js b/js/src/tests/non262/regress/regress-465136.js new file mode 100644 index 0000000000..ef2b96a4f5 --- /dev/null +++ b/js/src/tests/non262/regress/regress-465136.js @@ -0,0 +1,30 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465136; +var summary = 'false == ""'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + expect = 'true,true,true,true,true,'; + actual = ''; + + + for (var i=0;i<5;++i) actual += (false == '') + ','; + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465137.js b/js/src/tests/non262/regress/regress-465137.js new file mode 100644 index 0000000000..968b850be0 --- /dev/null +++ b/js/src/tests/non262/regress/regress-465137.js @@ -0,0 +1,30 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465137; +var summary = '!NaN is not false'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + expect = 'falsy,falsy,falsy,falsy,falsy,'; + actual = ''; + + + for (var i=0;i<5;++i) actual += (!(NaN) ? "falsy" : "truthy") + ','; + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465220.js b/js/src/tests/non262/regress/regress-465220.js new file mode 100644 index 0000000000..a17a23eae4 --- /dev/null +++ b/js/src/tests/non262/regress/regress-465220.js @@ -0,0 +1,40 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465220; +var summary = 'Do not assert: anti-nesting'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + expect = 'TypeError: can\'t convert o to primitive type'; + + + try + { + var o = {toString: function() { return (i > 2) ? this : "foo"; }}; + var s = ""; + for (var i = 0; i < 5; i++) + s += o + o; + print(s); + actual = 'No Exception'; + } + catch(ex) + { + actual = 'TypeError: can\'t convert o to primitive type'; + } + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465234.js b/js/src/tests/non262/regress/regress-465234.js new file mode 100644 index 0000000000..adb8476a6f --- /dev/null +++ b/js/src/tests/non262/regress/regress-465234.js @@ -0,0 +1,30 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465234; +var summary = '"" <= null'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + expect = true; + actual = true; + + + for (let j = 0; j < 5; ++j) actual = actual && ("" <= null); + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465236.js b/js/src/tests/non262/regress/regress-465236.js new file mode 100644 index 0000000000..7a07f17d57 --- /dev/null +++ b/js/src/tests/non262/regress/regress-465236.js @@ -0,0 +1,25 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465236; +var summary = 'TM: Do not assert: we should have converted to numbers already'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + for (let j = 0; j < 2; ++j) null <= null; + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465239.js b/js/src/tests/non262/regress/regress-465239.js new file mode 100644 index 0000000000..86033c362a --- /dev/null +++ b/js/src/tests/non262/regress/regress-465239.js @@ -0,0 +1,30 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465239; +var summary = '"1e+81" ^ 3'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + expect = '3,3,3,3,3,'; + actual = ''; + + + for (let j = 0; j < 5; ++j) actual += ("1e+81" ^ 3) + ','; + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465241.js b/js/src/tests/non262/regress/regress-465241.js new file mode 100644 index 0000000000..852b3d0a00 --- /dev/null +++ b/js/src/tests/non262/regress/regress-465241.js @@ -0,0 +1,30 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465241; +var summary = '"0" in [3]'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + expect = true; + actual = true; + + + for (let j = 0; j < 5; ++j) actual = actual && ("0" in [3]); + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465249.js b/js/src/tests/non262/regress/regress-465249.js new file mode 100644 index 0000000000..643ab4dd3a --- /dev/null +++ b/js/src/tests/non262/regress/regress-465249.js @@ -0,0 +1,27 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465249; +var summary = 'Do not assert: (m != JSVAL_INT) || isInt32(*vp)'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + + eval("for (let j = 0; j < 5; ++j) { (0x50505050) + (0x50505050); }"); + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465261.js b/js/src/tests/non262/regress/regress-465261.js new file mode 100644 index 0000000000..daad5c793c --- /dev/null +++ b/js/src/tests/non262/regress/regress-465261.js @@ -0,0 +1,31 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465261; +var summary = 'TM: Do not assert: '; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + + for (let z = 0; z < 2; ++z) { + for (let x of [0, true, (void 0), 0, (void 0)]) { + if(x){} + } + }; + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465262.js b/js/src/tests/non262/regress/regress-465262.js new file mode 100644 index 0000000000..b3c3e83468 --- /dev/null +++ b/js/src/tests/non262/regress/regress-465262.js @@ -0,0 +1,29 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465262; +var summary = 'truthiness of (3 > null)'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + + expect = 'true,true,true,true,true,'; + + for(j=0;j<5;++j) print(actual += "" + (3 > null) + ',') + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465272.js b/js/src/tests/non262/regress/regress-465272.js new file mode 100644 index 0000000000..fe7c012f2e --- /dev/null +++ b/js/src/tests/non262/regress/regress-465272.js @@ -0,0 +1,29 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465272; +var summary = 'subtraction'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + + expect = '3,3,3,3,3,'; + + for (j=0;j<5;++j) print(actual += "" + ((5) - 2) + ','); + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465308.js b/js/src/tests/non262/regress/regress-465308.js new file mode 100644 index 0000000000..553b98f6c9 --- /dev/null +++ b/js/src/tests/non262/regress/regress-465308.js @@ -0,0 +1,28 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465308; +var summary = '((0x60000009) * 0x60000009))'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + expect = '-1073741824,-1073741824,-1073741824,-1073741824,-1073741824,'; + + for (let j=0;j<5;++j) + print(actual += "" + (0 | ((0x60000009) * 0x60000009)) + ','); + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465347.js b/js/src/tests/non262/regress/regress-465347.js new file mode 100644 index 0000000000..207b860fe6 --- /dev/null +++ b/js/src/tests/non262/regress/regress-465347.js @@ -0,0 +1,49 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465347; +var summary = 'Test integer to id in js_Int32ToId'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + var o; + + o = new Array(); + + expect = undefined; + o[0xffffffff] = 'end'; + actual = o[-1]; + reportCompare(expect, actual, summary + ': 1'); + + expect = 42; + o['42'] = 42; + actual = o[42]; + reportCompare(expect, actual, summary + ': 2'); + + // + + o = new Object(); + + expect = undefined; + o[0xffffffff] = 'end'; + actual = o[-1]; + reportCompare(expect, actual, summary + ': 3'); + + expect = 42; + o['42'] = 42; + actual = o[42]; + reportCompare(expect, actual, summary + ': 4'); +} diff --git a/js/src/tests/non262/regress/regress-465366.js b/js/src/tests/non262/regress/regress-465366.js new file mode 100644 index 0000000000..3c06e4251c --- /dev/null +++ b/js/src/tests/non262/regress/regress-465366.js @@ -0,0 +1,36 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465366; +var summary = 'TM: JIT: error with multiplicative loop'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + + function f() + { + var k = 1; + for (var n = 0; n < 2; n++) { + k = (k * 10); + } + return k; + } + f(); + print(f()); + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465424.js b/js/src/tests/non262/regress/regress-465424.js new file mode 100644 index 0000000000..35a4dd3fe3 --- /dev/null +++ b/js/src/tests/non262/regress/regress-465424.js @@ -0,0 +1,27 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465424; +var summary = 'TM: issue with post-decrement operator'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + expect = '0,1,2,3,4,'; + + for (let j=0;j<5;++j) { jj=j; print(actual += '' + (jj--) + ',') } + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465454.js b/js/src/tests/non262/regress/regress-465454.js new file mode 100644 index 0000000000..3cdc72dda8 --- /dev/null +++ b/js/src/tests/non262/regress/regress-465454.js @@ -0,0 +1,28 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465454; +var summary = 'TM: do not crash with type-unstable loop'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + + for (let b of [(-1/0), new String(''), new String(''), null, (-1/0), + (-1/0), new String(''), new String(''), null]) '' + b; + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465460-01.js b/js/src/tests/non262/regress/regress-465460-01.js new file mode 100644 index 0000000000..b3a0cfbdb6 --- /dev/null +++ b/js/src/tests/non262/regress/regress-465460-01.js @@ -0,0 +1,29 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465460; +var summary = 'TM: valueOf in a loop'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + expect = '11111'; + + + (function(d) { for (let j = 0; j < 5; ++j) { actual += ('' + d); } })({valueOf: function() { return 1; }}); + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465460-02.js b/js/src/tests/non262/regress/regress-465460-02.js new file mode 100644 index 0000000000..48a6cc1688 --- /dev/null +++ b/js/src/tests/non262/regress/regress-465460-02.js @@ -0,0 +1,27 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465460; +var summary = 'TM: valueOf in a loop: do not assert'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + + for (let c of [null, null, null, {}]) { } + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465460-03.js b/js/src/tests/non262/regress/regress-465460-03.js new file mode 100644 index 0000000000..0c5ac8cc24 --- /dev/null +++ b/js/src/tests/non262/regress/regress-465460-03.js @@ -0,0 +1,26 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465460; +var summary = 'TM: valueOf in a loop: do not assert'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + for (let j of [null, 2, 3]) { } + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465460-04.js b/js/src/tests/non262/regress/regress-465460-04.js new file mode 100644 index 0000000000..497ee3be48 --- /dev/null +++ b/js/src/tests/non262/regress/regress-465460-04.js @@ -0,0 +1,27 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465460; +var summary = 'TM: valueOf in a loop: do not assert'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + + for (var j = 0; j < 3; ++j) { 1 & new Date; } + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465460-05.js b/js/src/tests/non262/regress/regress-465460-05.js new file mode 100644 index 0000000000..f33d103dd4 --- /dev/null +++ b/js/src/tests/non262/regress/regress-465460-05.js @@ -0,0 +1,27 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465460; +var summary = 'TM: valueOf in a loop: do not assert'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + + for (var j = 0; j < 3; ++j) { 1 & Date; } + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465460-06.js b/js/src/tests/non262/regress/regress-465460-06.js new file mode 100644 index 0000000000..e4ca0c1403 --- /dev/null +++ b/js/src/tests/non262/regress/regress-465460-06.js @@ -0,0 +1,27 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465460; +var summary = 'TM: valueOf in a loop: do not assert'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + + for (let x of [1, {}, 1, null, 1, {}, 1, null, 1]) { } + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465460-07.js b/js/src/tests/non262/regress/regress-465460-07.js new file mode 100644 index 0000000000..8c74fb5d50 --- /dev/null +++ b/js/src/tests/non262/regress/regress-465460-07.js @@ -0,0 +1,35 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465460; +var summary = 'TM: valueOf in a loop: do not assert'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + expect = actual = 'pass'; + + try + { + e = {}; for (j=0;j<3;++j) { 3 | e; } "PASS"; + } + catch(ex) + { + actual = ex + ''; + } + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465460-08.js b/js/src/tests/non262/regress/regress-465460-08.js new file mode 100644 index 0000000000..5eeea0c776 --- /dev/null +++ b/js/src/tests/non262/regress/regress-465460-08.js @@ -0,0 +1,27 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465460; +var summary = 'TM: valueOf in a loop: do not assert'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + + for (let _ of [{}, {}, null, null, null, null]) { } + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465460-10.js b/js/src/tests/non262/regress/regress-465460-10.js new file mode 100644 index 0000000000..779a1dea55 --- /dev/null +++ b/js/src/tests/non262/regress/regress-465460-10.js @@ -0,0 +1,27 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465460; +var summary = 'TM: valueOf in a loop: do not assert'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + + for (let i = 0; i < 2; ++i) { ({}) + 3; } + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465460-11.js b/js/src/tests/non262/regress/regress-465460-11.js new file mode 100644 index 0000000000..680b3d319d --- /dev/null +++ b/js/src/tests/non262/regress/regress-465460-11.js @@ -0,0 +1,27 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465460; +var summary = 'TM: valueOf in a loop: do not assert'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + + for (let d=0;d<2;++d) for (let a=0;a<1;++a) "" + (d && function(){}); + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465460-12.js b/js/src/tests/non262/regress/regress-465460-12.js new file mode 100644 index 0000000000..fe0b1af3ee --- /dev/null +++ b/js/src/tests/non262/regress/regress-465460-12.js @@ -0,0 +1,27 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465460; +var summary = 'TM: valueOf in a loop: do not assert'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + + for (var j = 0; j < 2; ++j) { if (null > "") { } } + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465483.js b/js/src/tests/non262/regress/regress-465483.js new file mode 100644 index 0000000000..056d9df297 --- /dev/null +++ b/js/src/tests/non262/regress/regress-465483.js @@ -0,0 +1,27 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465483; +var summary = 'Type instability leads to undefined being added as a string instead of as a number'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + expect = 'NaN'; + + for (i of [4, 'a', 'b', (void 0)]) print(actual = '' + (i + i)); + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465484.js b/js/src/tests/non262/regress/regress-465484.js new file mode 100644 index 0000000000..e4a598850b --- /dev/null +++ b/js/src/tests/non262/regress/regress-465484.js @@ -0,0 +1,25 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465484; +var summary = 'TM: Do not assert: _allocator.active[FST0] && _fpuStkDepth == -1 || ' + + '!_allocator.active[FST0] && _fpuStkDepth == 0'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + for (let a of [2, 2, 2]) { a %= a; a %= a; } + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465567-01.js b/js/src/tests/non262/regress/regress-465567-01.js new file mode 100644 index 0000000000..862c2abe43 --- /dev/null +++ b/js/src/tests/non262/regress/regress-465567-01.js @@ -0,0 +1,29 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465567; +var summary = 'TM: Weirdness with var, let, multiple assignments'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +expect = '99999'; + + +for (let j = 0; j < 5; ++j) { + var e; + e = 9; + print(actual += '' + e); + e = 47; + if (e & 0) { + let e; + } +} + + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/regress/regress-465567-02.js b/js/src/tests/non262/regress/regress-465567-02.js new file mode 100644 index 0000000000..821b66ff78 --- /dev/null +++ b/js/src/tests/non262/regress/regress-465567-02.js @@ -0,0 +1,25 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465567; +var summary = 'TM: Do not assert: JSVAL_TAG(v) == JSVAL_OBJECT'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + + +try +{ + eval("for (e of ['', true, 1, true, 1]) { e = null; if (0) { let e; var e; } }"); +} +catch(ex) +{ +} + + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/regress/regress-465686.js b/js/src/tests/non262/regress/regress-465686.js new file mode 100644 index 0000000000..1b91fddb0a --- /dev/null +++ b/js/src/tests/non262/regress/regress-465686.js @@ -0,0 +1,32 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465686; +var summary = 'Do not crash @ tiny_free_list_add_ptr'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + for (let b of [eval, eval, 4, 4]) { + ++b; + for (b of [(void 0), (void 0), (void 0), 3, (void 0), 3]) { + b ^= b; + for (var c of [1/0]) { + } + } + } + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-465688.js b/js/src/tests/non262/regress/regress-465688.js new file mode 100644 index 0000000000..acd68f44f5 --- /dev/null +++ b/js/src/tests/non262/regress/regress-465688.js @@ -0,0 +1,25 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 465688; +var summary = 'Do not assert: (m != JSVAL_INT) || isInt32(*vp),'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + for (let d of [-0x80000000, -0x80000000]) - -d; + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-466128.js b/js/src/tests/non262/regress/regress-466128.js new file mode 100644 index 0000000000..a9808b1a98 --- /dev/null +++ b/js/src/tests/non262/regress/regress-466128.js @@ -0,0 +1,28 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 466128; +var summary = 'Do not assert: !ti->stackTypeMap.matches(ti_other->stackTypeMap)'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + for (let a = 0; a < 3; ++a) { + for (let b of [1, 2, "three", 4, 5, 6, 7, 8]) { + } + } + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-466262.js b/js/src/tests/non262/regress/regress-466262.js new file mode 100644 index 0000000000..76406345d4 --- /dev/null +++ b/js/src/tests/non262/regress/regress-466262.js @@ -0,0 +1,31 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 466262; +var summary = 'Do not assert: f == f->root'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + + var e = 1; + for (var d = 0; d < 3; ++d) { + if (d == 2) { + e = ""; + } + } + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-466747.js b/js/src/tests/non262/regress/regress-466747.js new file mode 100644 index 0000000000..c1731dca49 --- /dev/null +++ b/js/src/tests/non262/regress/regress-466747.js @@ -0,0 +1,48 @@ +// |reftest| skip-if(xulRuntime.shell) +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 466747; +var summary = 'TM: Do not assert: fp->slots + fp->script->nfixed + ' + + 'js_ReconstructStackDepth(cx, fp->script, fp->regs->pc) == fp->regs->sp'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + gDelayTestDriverEnd = true; + + function newScriptWithLoop(m) + { + var ns = document.createElement("script"); + var nt = document.createTextNode("for (var q = 0; q < " + m + "; ++q) { }"); + ns.appendChild(nt); + return ns; + } + + function boom() + { + var div = document.createElement("div"); + div.appendChild(newScriptWithLoop(7)); + div.appendChild(newScriptWithLoop(1)); + document.body.appendChild(div); + + + reportCompare(expect, actual, summary); + gDelayTestDriverEnd = false; + jsTestDriverEnd(); + } + + window.addEventListener('load', boom, false); +} diff --git a/js/src/tests/non262/regress/regress-466787.js b/js/src/tests/non262/regress/regress-466787.js new file mode 100644 index 0000000000..8096910eae --- /dev/null +++ b/js/src/tests/non262/regress/regress-466787.js @@ -0,0 +1,30 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 466787; +var summary = 'TM: new Number() should stay a number during recording'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + expect = '4444'; + + + for (let j = 0; j < 4; ++j) { for (let one of [new Number(1)]) { + print(actual += '' + (3 + one)); } } + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-466905-01.js b/js/src/tests/non262/regress/regress-466905-01.js new file mode 100644 index 0000000000..1e039d24f8 --- /dev/null +++ b/js/src/tests/non262/regress/regress-466905-01.js @@ -0,0 +1,27 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 466905; +var summary = 'Do not assert: v_ins->isCall() && v_ins->callInfo() == &js_FastNewArray_ci'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + function f(a) { for (let c of a) [(c > 5) ? 'A' : 'B']; } + f([true, 8]); + f([2]); + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-466905-02.js b/js/src/tests/non262/regress/regress-466905-02.js new file mode 100644 index 0000000000..cfcc1b3e14 --- /dev/null +++ b/js/src/tests/non262/regress/regress-466905-02.js @@ -0,0 +1,26 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 466905; +var summary = 'Do not assert: v_ins->isCall() && v_ins->callInfo() == &js_FastNewArray_ci'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + for (var i = 0; i < 5; i++) + [(i > 3) ? 'a' : 'b']; + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-467495-01.js b/js/src/tests/non262/regress/regress-467495-01.js new file mode 100644 index 0000000000..da914db262 --- /dev/null +++ b/js/src/tests/non262/regress/regress-467495-01.js @@ -0,0 +1,25 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 467495; +var summary = 'Do not crash @ js_Interpret'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + (function() { x = 0; function x() { return 4; }; var x; const y = 1; })(); + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-467495-02.js b/js/src/tests/non262/regress/regress-467495-02.js new file mode 100644 index 0000000000..957e7d7c4b --- /dev/null +++ b/js/src/tests/non262/regress/regress-467495-02.js @@ -0,0 +1,31 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 467495; +var summary = 'Do not crash @ js_Interpret'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + try + { + eval("(function(){const y = 1; function x() '' let functional, x})();"); + } + catch(ex) + { + } + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-467495-03.js b/js/src/tests/non262/regress/regress-467495-03.js new file mode 100644 index 0000000000..5f8e756535 --- /dev/null +++ b/js/src/tests/non262/regress/regress-467495-03.js @@ -0,0 +1,44 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 467495; +var summary = 'TCF_FUN_CLOSURE_VS_VAR is necessary'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + function f(x) + { + actual = ''; + var g; + print(actual += typeof g + ','); + + if (x) + function g(){}; + + print(actual += g); + } + + expect = 'undefined,undefined'; + f(0); + + reportCompare(expect, actual, summary + ': f(0): '); + + expect = 'undefined,function g(){}'; + + f(1); + + reportCompare(expect, actual, summary + ': f(1): '); +} diff --git a/js/src/tests/non262/regress/regress-467495-04.js b/js/src/tests/non262/regress/regress-467495-04.js new file mode 100644 index 0000000000..d7227018ea --- /dev/null +++ b/js/src/tests/non262/regress/regress-467495-04.js @@ -0,0 +1,39 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 467495; +var summary = 'TCF_FUN_CLOSURE_VS_VAR is necessary'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + function g() { + if (1) + function x() {}; + var x; + const y = 1; + } + + try + { + g(); + } + catch(ex) + { + actual = ex + ''; + } + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-467495-05.js b/js/src/tests/non262/regress/regress-467495-05.js new file mode 100644 index 0000000000..f9089f354c --- /dev/null +++ b/js/src/tests/non262/regress/regress-467495-05.js @@ -0,0 +1,28 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 467495; +var summary = 'TCF_FUN_CLOSURE_VS_VAR is necessary'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + expect = '1'; + + function g(x) { if (1) function x() {} return x; } + print(actual = g(1) + ''); + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-467495-06.js b/js/src/tests/non262/regress/regress-467495-06.js new file mode 100644 index 0000000000..fc5ec361d9 --- /dev/null +++ b/js/src/tests/non262/regress/regress-467495-06.js @@ -0,0 +1,41 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 467495; +var summary = 'TCF_FUN_CLOSURE_VS_VAR is necessary'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + function f(x) + { + var y = 1; + if (Math) + function x() { } + if (Math) + function y() { } + return [x, y]; + } + + var r = f(0); + + if (typeof(r[0]) != "number") + actual += "Bad r[0]"; + + if (typeof(r[1]) != "function") + throw "Bad r[1]"; + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-468711.js b/js/src/tests/non262/regress/regress-468711.js new file mode 100644 index 0000000000..a771e4c625 --- /dev/null +++ b/js/src/tests/non262/regress/regress-468711.js @@ -0,0 +1,27 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 468711; +var summary = 'TM: Do not assert: !JS_ON_TRACE(cx)'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + + (5).toString(); for (let b of [3, this]) { b.toString(); } + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-469044.js b/js/src/tests/non262/regress/regress-469044.js new file mode 100644 index 0000000000..6221106b65 --- /dev/null +++ b/js/src/tests/non262/regress/regress-469044.js @@ -0,0 +1,68 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 469044; +var summary = 'type unstable globals'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + expect = '---000---000'; + actual = ''; + + for (var i = 0; i < 2; ++i) { + for (var e = 0; e < 2; ++e) { + } + var c = void 0; + print(actual += "---"); + for (var a = 0; a < 3; ++a) { + c <<= c; + print(actual += "" + c); + } + } + reportCompare(expect, actual, summary + ': 1'); + + expect = '00000000'; + actual = ''; + + print(""); + for (var i = 0; i < 2; ++i) { + for (var e = 0; e < 2; ++e) { + } + var c = void 0; + for (var a = 0; a < 3; ++a) { + c <<= c; + print(actual += "" + c); + } + print(actual += c); + } + reportCompare(expect, actual, summary + ': 2'); + + actual = ''; + print(""); + + for (var i = 0; i < 2; ++i) { + for (var e = 0; e < 2; ++e) { + } + var c = void 0; + for (var a = 0; a < 3; ++a) { + c <<= c; + Math; + print(actual += "" + c); + } + print(actual += c); + } + reportCompare(expect, actual, summary + ': 3'); +} diff --git a/js/src/tests/non262/regress/regress-469239-01.js b/js/src/tests/non262/regress/regress-469239-01.js new file mode 100644 index 0000000000..05de70dd91 --- /dev/null +++ b/js/src/tests/non262/regress/regress-469239-01.js @@ -0,0 +1,33 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 469239; +var summary = 'TM: Do not assert: entry->kpc == (jsbytecode*) atoms[index]'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + + for (let b=0;b<9;++b) { + for (let h of ['', 3, /x/]) { + for (c of [[], [], [], /x/]) { + '' + c; + } + } + } + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-469239-02.js b/js/src/tests/non262/regress/regress-469239-02.js new file mode 100644 index 0000000000..b36cd76ce2 --- /dev/null +++ b/js/src/tests/non262/regress/regress-469239-02.js @@ -0,0 +1,33 @@ +/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 469239; +var summary = 'TM: Do not assert: ATOM_IS_STRING(atom)'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + + for (let b=0;b<9;++b) { + for (let h of [33, 3, /x/]) { + for (c of [[], [], [], /x/]) { + '' + c; + } + } + } + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-469547.js b/js/src/tests/non262/regress/regress-469547.js new file mode 100644 index 0000000000..4cb0fc056a --- /dev/null +++ b/js/src/tests/non262/regress/regress-469547.js @@ -0,0 +1,31 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 469547; +var summary = 'Do not crash with: for (let [,] of [[], [], null]) {}'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + try + { + for (let [,] of [[], [], null]) {} + } + catch(ex) + { + } + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-469625-02.js b/js/src/tests/non262/regress/regress-469625-02.js new file mode 100644 index 0000000000..03751d5b54 --- /dev/null +++ b/js/src/tests/non262/regress/regress-469625-02.js @@ -0,0 +1,32 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: Jason Orendorff + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 469625; +var summary = 'group assignment with rhs containing holes'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + expect = 'y'; + + Array.prototype[1] = 'y'; + var [x, y, z] = ['x', , 'z']; + + actual = y; + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-469625-03.js b/js/src/tests/non262/regress/regress-469625-03.js new file mode 100644 index 0000000000..28dc11c5d4 --- /dev/null +++ b/js/src/tests/non262/regress/regress-469625-03.js @@ -0,0 +1,38 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: Jason Orendorff + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 469625; +var summary = 'Do not assert: script->objectsOffset != 0'; +var actual = ''; +var expect = ''; + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + function f(x) { + var [a, b, [c0, c1]] = [x, x, x]; + } + + expect = /TypeError: .*\[\.\.\.\]\[Symbol.iterator\]\(\)\.next\(\)\.value is null/; + actual = 'No Error'; + try + { + f(null); + } + catch(ex) + { + actual = ex + ''; + } + reportMatch(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-469758.js b/js/src/tests/non262/regress/regress-469758.js new file mode 100644 index 0000000000..426f6010e2 --- /dev/null +++ b/js/src/tests/non262/regress/regress-469758.js @@ -0,0 +1,14 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +var err; +try { + {let i=1} + {let j=1; [][j][2]} +} catch (e) { + err = e; +} +assertEq(err instanceof TypeError, true); +assertEq(err.message.endsWith("[][j] is undefined"), true); + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/regress/regress-469937.js b/js/src/tests/non262/regress/regress-469937.js new file mode 100644 index 0000000000..753735c15d --- /dev/null +++ b/js/src/tests/non262/regress/regress-469937.js @@ -0,0 +1,27 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 469937; +var summary = 'Properties without DontEnum are sometimes not enumerated'; +var actual = false; +var expect = true; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +(function(){ + var o = { } + o.PageLeft = 1; + o.Rect2 = 6; + delete o.Rect2; + for (var p in o); + o.Rect3 = 7; + found = false; + for (var p in o) if (p == 'Rect3') found = true; + actual = found; +})(); + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/regress/regress-470061.js b/js/src/tests/non262/regress/regress-470061.js new file mode 100644 index 0000000000..5d2ae75815 --- /dev/null +++ b/js/src/tests/non262/regress/regress-470061.js @@ -0,0 +1,40 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 470061; +var summary = 'TM: Do not assert: cx->fp->regs->pc == f->ip && f->root == f'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + + function x (w, z) { + var h = 0; + var q = 0; + while (q < 300) { + while (w) { + } + ++q; + if (q % 4 == 1) { + h = Math.ceil(z); + } + } + } + + x(false, 40); + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-470187-01.js b/js/src/tests/non262/regress/regress-470187-01.js new file mode 100644 index 0000000000..c1f40b5449 --- /dev/null +++ b/js/src/tests/non262/regress/regress-470187-01.js @@ -0,0 +1,25 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 470187; +var summary = 'Do not assert: entry->kpc == (jsbytecode*) atoms[index]'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + for (var j=0;j<3;++j) ({valueOf: function(){return 2}}) - /x/; + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-470187-02.js b/js/src/tests/non262/regress/regress-470187-02.js new file mode 100644 index 0000000000..da8ab58396 --- /dev/null +++ b/js/src/tests/non262/regress/regress-470187-02.js @@ -0,0 +1,24 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 470187; +var summary = 'Do not assert: ATOM_IS_STRING(atom)'; +var actual = ''; +var expect = ''; + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + for (var j=0;j<3;++j) ({valueOf: function(){return 2}}) - []; + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-470223.js b/js/src/tests/non262/regress/regress-470223.js new file mode 100644 index 0000000000..aea6f1310b --- /dev/null +++ b/js/src/tests/non262/regress/regress-470223.js @@ -0,0 +1,35 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 470223; +var summary = 'TM: Do not crash @ js_NewObjectWithGivenProto'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + + function F(A) { + for (R = [], s = 0; (m = A.indexOf("m", s++)) >= 0; ) + R.push([m]); + for (i = R.length; i--; ) { + let r = R[i]; + if (r[0]); + } + } + F("m"); F("mm"); + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-470388-01.js b/js/src/tests/non262/regress/regress-470388-01.js new file mode 100644 index 0000000000..13d22a5ecc --- /dev/null +++ b/js/src/tests/non262/regress/regress-470388-01.js @@ -0,0 +1,25 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 470388; +var summary = 'TM: Do not assert: !(fp->flags & JSFRAME_POP_BLOCKS)'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + for (let x of [function(){}, new Boolean(false), function(){}]) {} + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-470758-01.js b/js/src/tests/non262/regress/regress-470758-01.js new file mode 100644 index 0000000000..b3d166ca2b --- /dev/null +++ b/js/src/tests/non262/regress/regress-470758-01.js @@ -0,0 +1,27 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: Blake Kaplan + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 470758; +var summary = 'Do not crash with eval upvars'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + (function() { var k; eval("for (var k in {});") })() + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-470758-02.js b/js/src/tests/non262/regress/regress-470758-02.js new file mode 100644 index 0000000000..a0aa3ac000 --- /dev/null +++ b/js/src/tests/non262/regress/regress-470758-02.js @@ -0,0 +1,29 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: Blake Kaplan + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 470758; +var summary = 'Promote evald initializer into upvar'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + expect = 5; + + (function(){var x;eval("for (x = 0; x < 5; x++);");print(actual = x);})(); + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-471660.js b/js/src/tests/non262/regress/regress-471660.js new file mode 100644 index 0000000000..a0fe35f3f7 --- /dev/null +++ b/js/src/tests/non262/regress/regress-471660.js @@ -0,0 +1,34 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 471660; +var summary = 'TM: Do not assert: !(fp->flags & JSFRAME_POP_BLOCKS)'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + + y = {"a":1}; + + for (var w = 0; w < 5; ++w) { + + { let y; do break ; while (true); } + for (let x of [{}, function(){}]) {y} + + } + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-472533.js b/js/src/tests/non262/regress/regress-472533.js new file mode 100644 index 0000000000..9a56df9d02 --- /dev/null +++ b/js/src/tests/non262/regress/regress-472533.js @@ -0,0 +1,25 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 472533; +var summary = 'Do not crash with loop, replace, regexp'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + for (var j = 0; j < 4; ++j) ''.replace('', /x/); + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-474769.js b/js/src/tests/non262/regress/regress-474769.js new file mode 100644 index 0000000000..462a4432ec --- /dev/null +++ b/js/src/tests/non262/regress/regress-474769.js @@ -0,0 +1,32 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 474769; +var summary = 'TM: nested type-unstable for loops'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + expect = 1; + + + for (b of [1, 1, 1, 1.5, 1, 1]) { + (function() { for (let h of [0, 0, 1.4, ""]) {} })(); + } + actual = b; + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-474771-01.js b/js/src/tests/non262/regress/regress-474771-01.js new file mode 100644 index 0000000000..7971cc769d --- /dev/null +++ b/js/src/tests/non262/regress/regress-474771-01.js @@ -0,0 +1,38 @@ +// |reftest| skip-if(Android) +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 474771; +var summary = 'gczeal, prototype mangling, for..in'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + expect = 'PASS'; + if (typeof gczeal == 'function') + { + gczeal(2); + } + + Object.prototype.q = 3; + for (let x of [6, 7]) { } print(actual = "PASS"); + + if (typeof gczeal == 'function') + { + gczeal(0); + } + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-474771.js b/js/src/tests/non262/regress/regress-474771.js new file mode 100644 index 0000000000..4b3985edad --- /dev/null +++ b/js/src/tests/non262/regress/regress-474771.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(Android) +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 474771; +var summary = 'TM: do not halt execution with gczeal, prototype mangling, for..in'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + expect = 'PASS'; + + if (typeof gczeal == 'function') + { + gczeal(2); + } + + Object.prototype.q = 3; + for (let x of [6, 7]) { } print(actual = "PASS"); + + + delete Object.prototype.q; + + if (typeof gczeal == 'function') + { + gczeal(0); + } + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-474935.js b/js/src/tests/non262/regress/regress-474935.js new file mode 100644 index 0000000000..7e311156d7 --- /dev/null +++ b/js/src/tests/non262/regress/regress-474935.js @@ -0,0 +1,37 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 474935; +var summary = 'Do not assert: !ti->typeMap.matches(ti_other->typeMap)'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + + var a = ["", 0, 0, 0, 0, 0, "", "", 0, "", 0, ""]; + var i = 0; + var g = 0; + for (let e of a) { + "" + [e]; + if (i == 3 || i == 7) { + for (g of [1]) { + } + } + ++i; + } + + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/regress/regress-475469.js b/js/src/tests/non262/regress/regress-475469.js new file mode 100644 index 0000000000..ccca629408 --- /dev/null +++ b/js/src/tests/non262/regress/regress-475469.js @@ -0,0 +1,30 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 475469; +var summary = 'TM: Do not crash @ FramePCOffset'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + +// print('Note this test originally required jit enabled with the environment '); +// print('variable TRACEMONKEY=verbose defined. Note that the calls to enable '); +// print('jit are necessary for the crash.'); + + [1,2,3].map(function(v, i, t) { return /a/gi.exec(v); }); + + reportCompare(expect, actual, summary); +} + diff --git a/js/src/tests/non262/regress/regress-475645-01.js b/js/src/tests/non262/regress/regress-475645-01.js new file mode 100644 index 0000000000..04fb570bc5 --- /dev/null +++ b/js/src/tests/non262/regress/regress-475645-01.js @@ -0,0 +1,44 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 475645; +var summary = 'Do not crash @ nanojit::LIns::isop'; +var actual = ''; +var expect = ''; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + + linkarr = new Array(); + picarr = new Array(); + textarr = new Array(); + var f=161; + var t=27; + var pics = ""; + var links = ""; + var texts = ""; + var s = f+t; + var d = "1"; + picarr[2] = "2"; + for(i=1;i' + + 'for (var i = 0; i != 1000; ++i)' + + ' this["a"+i] = 0;' + + 'eval("var x");' + + 'for (var i = 0; i != 1000; ++i)' + + ' delete this["a"+i];' + + '<\/script>' + ); + + document.write( + '